[Patch] update of the alpha vms bfd back-end

Tristan Gingold gingold@adacore.com
Tue Feb 17 11:22:00 GMT 2009


Hi,

at AdaCore we have used binutils for Alpha VMS for a long time and we have
patches in our own tree to fix issues and add features.
This first large patch updates the bfd back-end.  It mostly add support for
handling relocation and debug informations.
Most of the patch only modified vms-* files but it only adds relocations to
reloc.c and modify VMS specific code in bfdio.c

Tristan.
bfd/
2009-02-17  Tristan Gingold  <gingold@adacore.com>
	    Eric Botcazou  <ebotcazou@adacore.com>
	    Douglas B Rupp  <rupp@gnat.com>

	Major update of alpha vms back-end.
	* 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.

-------------- next part --------------
bfd/
2009-02-17  Tristan Gingold  <gingold@adacore.com>
	    Eric Botcazou  <ebotcazou@adacore.com>
	    Douglas B Rupp  <rupp@gnat.com>

	Major update of alpha vms back-end.
	* 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.

Index: bfd/bfdio.c
===================================================================
RCS file: /cvs/src/src/bfd/bfdio.c,v
retrieving revision 1.19
diff -c -r1.19 bfdio.c
*** bfd/bfdio.c	14 Nov 2008 09:57:33 -0000	1.19
--- bfd/bfdio.c	17 Feb 2009 11:13:08 -0000
***************
*** 102,114 ****
      }
    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));
      }
  #else /* !VMS */
  #if defined (HAVE_FOPEN64)
--- 102,122 ----
      }
    else
      {
!       /* 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)
Index: bfd/makefile.vms
===================================================================
RCS file: /cvs/src/src/bfd/makefile.vms,v
retrieving revision 1.2
diff -c -r1.2 makefile.vms
*** bfd/makefile.vms	14 Nov 2008 09:57:33 -0000	1.2
--- bfd/makefile.vms	17 Feb 2009 11:13:09 -0000
***************
*** 36,48 ****
  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")
  else
  DEFS=/define=(SELECT_VECS="&vms_vax_vec",SELECT_ARCHITECTURES="&bfd_vax_arch",\
! "HAVE_vms_vax_vec=1","unlink=remove","const=")
  endif
! CFLAGS=/noopt/debug/show=incl/name=(as_is,shortened)/include=([],[-.include])$(DEFS)/warnings=disable=(missingreturn,longextern)
  endif
  
  
--- 36,50 ----
  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")
  else
  DEFS=/define=(SELECT_VECS="&vms_vax_vec",SELECT_ARCHITECTURES="&bfd_vax_arch",\
!   "HAVE_vms_vax_vec=1","unlink=remove")
  endif
! OPT=/noopt/debug
! CFLAGS=/name=(as_is,shortened)/include=([],[-.include])$(DEFS)$(OPT)
  endif
  
  
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.182
diff -c -r1.182 reloc.c
*** bfd/reloc.c	3 Feb 2009 14:36:46 -0000	1.182
--- bfd/reloc.c	17 Feb 2009 11:13:09 -0000
***************
*** 2110,2115 ****
--- 2110,2139 ----
    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
Index: bfd/vms-gsd.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-gsd.c,v
retrieving revision 1.21
diff -c -r1.21 vms-gsd.c
*** bfd/vms-gsd.c	3 Jul 2007 14:26:42 -0000	1.21
--- bfd/vms-gsd.c	17 Feb 2009 11:13:09 -0000
***************
*** 1,9 ****
  /* 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.
  
!    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)
--- 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, 2009 Free Software Foundation, Inc.
  
!    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,51 ****
--- 49,55 ----
  #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,138 ****
--- 137,147 ----
        (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,202 ****
--- 206,242 ----
  
  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,266 ****
  
  /* Input routines.  */
  
  /* 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;
--- 264,278 ----
  
  /* 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)
  {
    int gsd_type, gsd_size;
    asection *section;
    unsigned char *vms_rec;
***************
*** 300,306 ****
        vms_rec = PRIV (vms_rec);
  
        if (objtype == OBJ_S_C_GSD)
! 	gsd_type = *vms_rec;
        else
  	{
  	  _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
--- 312,318 ----
        vms_rec = PRIV (vms_rec);
  
        if (objtype == OBJ_S_C_GSD)
! 	gsd_type = vms_rec[0];
        else
  	{
  	  _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
***************
*** 322,328 ****
  	    vms_debug (4, "GSD_S_C_PSC\n");
  #endif
  	    /* If this section isn't a bfd section.  */
! 	    if (PRIV (is_vax) && (psect_idx < (abfd->section_count-1)))
  	      {
  		/* Check for temporary section from TIR record.  */
  		if (psect_idx < PRIV (section_count))
--- 334,340 ----
  	    vms_debug (4, "GSD_S_C_PSC\n");
  #endif
  	    /* If this section isn't a bfd section.  */
! 	    if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1)))
  	      {
  		/* Check for temporary section from TIR record.  */
  		if (psect_idx < PRIV (section_count))
***************
*** 362,368 ****
  	    base_addr += section->size;
  
  	    /* Global section is common symbol.  */
- 
  	    if (old_flags & GPS_S_M_GBL)
  	      {
  		entry = _bfd_vms_enter_symbol (abfd, name);
--- 374,379 ----
***************
*** 496,516 ****
  		else
  		  psect = vms_rec[value_offset-1];
  
! 		symbol->section = (asection *) (size_t) psect;
  #if VMS_DEBUG
! 		vms_debug (4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount,
! 			   symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
  #endif
  	      }
  	    else
  	      {
  		/* Symbol reference.  */
- 		symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
  #if VMS_DEBUG
! 		vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n",
! 			   abfd->symcount, symbol->name, symbol->section->name,
! 			   symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
  #endif
  	      }
  
  	    gsd_size = vms_rec[name_offset] + name_offset + 1;
--- 507,526 ----
  		else
  		  psect = vms_rec[value_offset-1];
  
! 		symbol->section = (asection *)(unsigned long)psect;
  #if VMS_DEBUG
! 		vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount,
! 			  symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags));
  #endif
  	      }
  	    else
  	      {
  		/* Symbol reference.  */
  #if VMS_DEBUG
! 		vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
! 			   symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
  #endif
+ 		symbol->section = (asection *)(unsigned long)-1;
  	      }
  
  	    gsd_size = vms_rec[name_offset] + name_offset + 1;
***************
*** 574,592 ****
  	case EGSD_S_C_PSC + EVAX_OFFSET:
  	  {
  	    /* Program section definition.  */
! 	    name = _bfd_vms_save_counted_string (vms_rec + 12);
  	    section = bfd_make_section (abfd, name);
  	    if (!section)
  	      return -1;
! 	    old_flags = bfd_getl16 (vms_rec + 6);
! 	    section->size = bfd_getl32 (vms_rec + 8);	/* Allocation.  */
  	    new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
  					     section->size > 0);
  	    if (old_flags & EGPS_S_V_REL)
  	      new_flags |= SEC_RELOC;
  	    if (!bfd_set_section_flags (abfd, section, new_flags))
  	      return -1;
! 	    section->alignment_power = vms_rec[4];
  	    align_addr = (1 << section->alignment_power);
  	    if ((base_addr % align_addr) != 0)
  	      base_addr += (align_addr - (base_addr % align_addr));
--- 584,602 ----
  	case EGSD_S_C_PSC + EVAX_OFFSET:
  	  {
  	    /* Program section definition.  */
! 	    name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG);
  	    section = bfd_make_section (abfd, name);
  	    if (!section)
  	      return -1;
! 	    old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS);
! 	    section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC);
  	    new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
  					     section->size > 0);
  	    if (old_flags & EGPS_S_V_REL)
  	      new_flags |= SEC_RELOC;
  	    if (!bfd_set_section_flags (abfd, section, new_flags))
  	      return -1;
! 	    section->alignment_power = vms_rec[EGPS_S_B_ALIGN];
  	    align_addr = (1 << section->alignment_power);
  	    if ((base_addr % align_addr) != 0)
  	      base_addr += (align_addr - (base_addr % align_addr));
***************
*** 595,603 ****
  	    section->contents = bfd_zmalloc (section->size);
  	    if (section->contents == NULL)
  	      return -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, "%d bytes at 0x%08lx (mem %p)\n",
  		       section->size, section->vma, section->contents);
  #endif
--- 605,614 ----
  	    section->contents = bfd_zmalloc (section->size);
  	    if (section->contents == NULL)
  	      return -1;
+ 	    section->filepos = (unsigned int)-1;
  #if VMS_DEBUG
! 	    vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ",
! 		       section->index, name, old_flags, flag2str(gpsflagdesc, old_flags));
  	    vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
  		       section->size, section->vma, section->contents);
  #endif
***************
*** 606,655 ****
  
  	case EGSD_S_C_SYM + EVAX_OFFSET:
  	  {
! 	    /* Symbol specification (definition or reference).  */
  	    symbol = bfd_make_empty_symbol (abfd);
  	    if (symbol == 0)
  	      return -1;
  
! 	    old_flags = bfd_getl16 (vms_rec + 6);
  	    new_flags = BSF_NO_FLAGS;
  
  	    if (old_flags & EGSY_S_V_WEAK)
  	      new_flags |= BSF_WEAK;
  
! 	    if (vms_rec[6] & EGSY_S_V_DEF)
  	      {
  		/* Symbol definition.  */
- 		symbol->name = _bfd_vms_save_counted_string (vms_rec + 32);
  		if (old_flags & EGSY_S_V_NORM)
- 		  /* Proc def.  */
  		  new_flags |= BSF_FUNCTION;
! 
! 		symbol->value = bfd_getl64 (vms_rec + 8);
! 		symbol->section = (asection *) ((unsigned long) bfd_getl32 (vms_rec + 28));
! #if VMS_DEBUG
! 		vms_debug (4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount,
! 			   symbol->name, (int) symbol->section, old_flags,
! 			   flag2str (gsyflagdesc, old_flags));
  #endif
  	      }
  	    else
  	      {
  		/* Symbol reference.  */
! 		symbol->name = _bfd_vms_save_counted_string (vms_rec + 8);
  #if VMS_DEBUG
! 		vms_debug (4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
! 			  symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
  #endif
! 		symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
  	      }
  
  	    symbol->flags = new_flags;
  
! 	    /* Save symbol in vms_symbol_table.  */
! 	    entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
! 							  symbol->name,
! 							  TRUE, FALSE);
  	    if (entry == NULL)
  	      {
  		bfd_set_error (bfd_error_no_memory);
--- 617,668 ----
  
  	case EGSD_S_C_SYM + EVAX_OFFSET:
  	  {
! 	    /* Global symbol specification (definition or reference).  */
  	    symbol = bfd_make_empty_symbol (abfd);
  	    if (symbol == 0)
  	      return -1;
  
! 	    old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS);
  	    new_flags = BSF_NO_FLAGS;
  
  	    if (old_flags & EGSY_S_V_WEAK)
  	      new_flags |= BSF_WEAK;
  
! 	    if (old_flags & EGSY_S_V_DEF)
  	      {
  		/* Symbol definition.  */
  		if (old_flags & EGSY_S_V_NORM)
  		  new_flags |= BSF_FUNCTION;
! 		symbol->name =
! 		  _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG);
! 		symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE);
! 		symbol->section =
! 		  (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX);
! #if VMS_DEBUG
! 		vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n",
! 			   abfd->symcount, symbol->name, (long)symbol->section,
! 			   old_flags, flag2str (gsyflagdesc, old_flags));
  #endif
  	      }
  	    else
  	      {
  		/* Symbol reference.  */
! 		symbol->name =
! 		  _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG);
  #if VMS_DEBUG
! 		vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n",
! 			   abfd->symcount, symbol->name, old_flags,
! 			   flag2str (gsyflagdesc, old_flags));
  #endif
! 		symbol->section = (asection *)(unsigned long)-1;
  	      }
  
  	    symbol->flags = new_flags;
  
! 	    /* Register symbol in VMS symbol table.  */
! 	    entry = (vms_symbol_entry *) bfd_hash_lookup
! 	      (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE);
! 
  	    if (entry == NULL)
  	      {
  		bfd_set_error (bfd_error_no_memory);
***************
*** 672,682 ****
  	  }
  	  break;
  
! 	case EGSD_S_C_IDC + EVAX_OFFSET:
  	  break;
  
  	default:
! 	  (*_bfd_error_handler) (_("unknown gsd/egsd subtype %d"), gsd_type);
  	  bfd_set_error (bfd_error_bad_value);
  	  return -1;
  	}
--- 685,757 ----
  	  }
  	  break;
  
! 	case EGSD_S_C_SYMG + EVAX_OFFSET:
! 	  {
! 	    /* Universal symbol specification (definition).  */
! 	    symbol = bfd_make_empty_symbol (abfd);
! 	    if (symbol == 0)
! 	      return -1;
! 
! 	    old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS);
! 	    new_flags = BSF_NO_FLAGS;
! 
! 	    if (old_flags & EGSY_S_V_WEAK)
! 	      new_flags |= BSF_WEAK;
! 
! 	    if (old_flags & EGSY_S_V_DEF) /* symbol definition */
! 	      {
! 		if (old_flags & EGSY_S_V_NORM)
! 		  new_flags |= BSF_FUNCTION;
! 
! 		symbol->name =
! 		  _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG);
! 
! 		/* For BSF_FUNCTION symbols, the entry point is in LP_1
! 		   and the descriptor in LP_2.  For other symbols, the
! 		   unique value is in LP_2.  */
! 		symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2);
! 
! 		/* Adding this offset is necessary in order for GDB to
! 		   read the DWARF-2 debug info from shared libraries.  */
! 		if (abfd->flags & DYNAMIC
! 		    && strstr (symbol->name, "$DWARF2.DEBUG") != 0)
! 		  symbol->value += PRIV (symvva);
! 	      }
! 	    else /* symbol reference */
! 	      (*_bfd_error_handler) ("Invalid EGST reference");
! 
! 	    symbol->flags = new_flags;
! 
! 	    if (register_universal_symbol (abfd, symbol, old_flags) < 0)
! 	      return -1;
! 
! 	    /* Make a second symbol for the entry point.  */
! 	    if (symbol->flags & BSF_FUNCTION)
! 	      {
! 		asymbol *en_sym;
! 		char *name = bfd_alloc (abfd, strlen (symbol->name) + 5);
! 
! 		en_sym = bfd_make_empty_symbol (abfd);
! 		if (en_sym == 0)
! 		  return -1;
! 
! 		strcpy (name, symbol->name);
! 		strcat (name, "..en");
! 
! 		en_sym->name = name;
! 		en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);
! 
! 		if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
! 		  return -1;
! 	      }
! 	  }
  	  break;
  
+ 	case EGSD_S_C_IDC + EVAX_OFFSET:
+   	  break;
+ 
  	default:
! 	  (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
  	  bfd_set_error (bfd_error_bad_value);
  	  return -1;
  	}
***************
*** 691,697 ****
    return 0;
  }
  
! /* Output routines.  */
  
  /* Write section and symbol directory of bfd abfd.  */
  
--- 766,844 ----
    return 0;
  }
  
! /* 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,710 ****
--- 852,858 ----
    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,735 ****
--- 878,888 ----
        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,780 ****
--- 928,938 ----
  	    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,802 ****
  
        _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
        _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
        if (bfd_is_com_section (section))
! 	new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
        else
  	new_flags = vms_esecflag_by_name (evax_section_flags, sname,
  					  section->size > 0);
  
        _bfd_vms_output_short (abfd, new_flags);
        _bfd_vms_output_long (abfd, (unsigned long) section->size);
        _bfd_vms_output_counted (abfd, sname);
        _bfd_vms_output_flush (abfd);
  
        last_index = section->index;
        section = section->next;
      }
  
--- 943,976 ----
  
        _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
        _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
+ 
        if (bfd_is_com_section (section))
! 	new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD
! 		     | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
        else
  	new_flags = vms_esecflag_by_name (evax_section_flags, sname,
  					  section->size > 0);
  
+       /* 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,830 ****
        if (old_flags & BSF_FILE)
  	continue;
  
!       if (((old_flags & (BSF_GLOBAL | BSF_WEAK)) == 0)	/* Not xdef...  */
! 	  && (!bfd_is_und_section (symbol->section)))	/* ...and not xref.  */
! 	continue;					/* Dont output.  */
  
        /* 13 bytes egsd, max 64 chars name -> should be 77 bytes.  */
        if (_bfd_vms_output_check (abfd, 80) < 0)
--- 996,1006 ----
        if (old_flags & BSF_FILE)
  	continue;
  
!       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,852 ****
  
        if (old_flags & BSF_WEAK)
  	new_flags |= EGSY_S_V_WEAK;
!       if (bfd_is_com_section (symbol->section))
  	new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
  
        if (old_flags & BSF_FUNCTION)
--- 1022,1028 ----
  
        if (old_flags & BSF_WEAK)
  	new_flags |= EGSY_S_V_WEAK;
!       if (bfd_is_com_section (symbol->section))		/* .comm  */
  	new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
  
        if (old_flags & BSF_FUNCTION)
***************
*** 854,860 ****
  	  new_flags |= EGSY_S_V_NORM;
  	  new_flags |= EGSY_S_V_REL;
  	}
!       if (old_flags & (BSF_GLOBAL | BSF_WEAK))
  	{
  	  new_flags |= EGSY_S_V_DEF;
  	  if (!bfd_is_abs_section (symbol->section))
--- 1030,1036 ----
  	  new_flags |= EGSY_S_V_NORM;
  	  new_flags |= EGSY_S_V_REL;
  	}
!       if (old_flags & BSF_GLOBAL)
  	{
  	  new_flags |= EGSY_S_V_DEF;
  	  if (!bfd_is_abs_section (symbol->section))
***************
*** 862,868 ****
  	}
        _bfd_vms_output_short (abfd, new_flags);
  
!       if (old_flags & (BSF_GLOBAL | BSF_WEAK))
  	{
  	  /* Symbol definition.  */
  	  uquad code_address = 0;
--- 1038,1044 ----
  	}
        _bfd_vms_output_short (abfd, new_flags);
  
!       if (old_flags & BSF_GLOBAL)
  	{
  	  /* Symbol definition.  */
  	  uquad code_address = 0;
***************
*** 871,880 ****
  
  	  if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
  	    {
! 	      code_address = ((asymbol *) (symbol->udata.p))->value;
! 	      ca_psindx = ((asymbol *) (symbol->udata.p))->section->index;
  	    }
! 	  psindx = symbol->section->index;
  
  	  _bfd_vms_output_quad (abfd, symbol->value);
  	  _bfd_vms_output_quad (abfd, code_address);
--- 1047,1065 ----
  
  	  if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
  	    {
! 	      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;
  	    }
! 	  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);
Index: bfd/vms-hdr.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-hdr.c,v
retrieving revision 1.22
diff -c -r1.22 vms-hdr.c
*** bfd/vms-hdr.c	14 Nov 2008 09:57:33 -0000	1.22
--- bfd/vms-hdr.c	17 Feb 2009 11:13:09 -0000
***************
*** 1,14 ****
  /* 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.
  
     HDR record handling functions
     EMH record handling functions
!    and
     EOM record handling functions
     EEOM record handling functions
  
     Written by Klaus K"ampf (kkaempf@rmi.de)
  
     This program is free software; you can redistribute it and/or modify
--- 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, 2008, 2009 Free Software Foundation, Inc.
  
     HDR record handling functions
     EMH record handling functions
! 
     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,44 ****
--- 56,75 ----
  #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,99 ****
        break;
  
      case MHD_S_C_LNM:
!       PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
        break;
  
      case MHD_S_C_SRC:
!       PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
        break;
  
      case MHD_S_C_TTL:
!       PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
        break;
  
      case EMH_S_C_MHD + EVAX_OFFSET:
--- 116,130 ----
        break;
  
      case MHD_S_C_LNM:
!       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_size - 2));
        break;
  
      case MHD_S_C_TTL:
!       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,124 ****
        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));
        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));
        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));
        break;
  
      case MHD_S_C_CPR:
--- 141,155 ----
        break;
  
      case EMH_S_C_LNM + EVAX_OFFSET:
!       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_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_size - 6));
        break;
  
      case MHD_S_C_CPR:
***************
*** 189,194 ****
--- 220,226 ----
    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,239 ****
  
        fptr = bfd_get_filename (abfd);
        fname = strdup (fptr);
        fout = strrchr (fname, ']');
!       if (fout == 0)
  	fout = strchr (fname, ':');
!       if (fout != 0)
  	fout++;
        else
  	fout = fname;
  
        /* Strip .obj suffix.  */
!       fptr = strrchr (fname, '.');
!       if ((fptr != 0)
! 	  && (strcasecmp (fptr, ".OBJ") == 0))
  	*fptr = 0;
  
        fptr = fout;
        while (*fptr != 0)
  	{
  	  *fptr = TOUPPER (*fptr);
  	  fptr++;
! 	  if ((*fptr == ';')
! 	     || ((fptr - fout) > 31))
  	    *fptr = 0;
  	}
        _bfd_vms_output_counted (abfd, fout);
--- 245,278 ----
  
        fptr = bfd_get_filename (abfd);
        fname = strdup (fptr);
+ 
+       /* Strip VMS path.  */
        fout = strrchr (fname, ']');
!       if (fout == NULL)
  	fout = strchr (fname, ':');
!       if (fout != NULL)
  	fout++;
        else
  	fout = fname;
  
+       /* Strip UNIX path.  */
+       fptr = strrchr (fout, '/');
+       if (fptr != NULL)
+ 	fout = fptr + 1;
+ 
        /* Strip .obj suffix.  */
!       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)
  	    *fptr = 0;
  	}
        _bfd_vms_output_counted (abfd, fout);
***************
*** 243,255 ****
      _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_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"));
    _bfd_vms_output_flush (abfd);
  
    /* SRC.  */
--- 282,295 ----
      _bfd_vms_output_counted (abfd, "NONAME");
  
    _bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
!   _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);
!   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,329 ****
      }
    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)
  	{
  	  (*_bfd_error_handler) (_("Object module NOT error-free !\n"));
  	  bfd_set_error (bfd_error_bad_value);
--- 360,369 ----
      }
    else
      {
!       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,341 ****
        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);
  
  	   abfd->start_address = PRIV (eom_data).eom_l_tfradr;
  	}
--- 373,383 ----
        if (PRIV (rec_size) > 10)
  	{
  	   PRIV (eom_data).eom_has_transfer = TRUE;
! 	   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,379 ****
--- 419,1419 ----
    _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;
+ }
Index: bfd/vms-misc.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-misc.c,v
retrieving revision 1.29
diff -c -r1.29 vms-misc.c
*** bfd/vms-misc.c	30 Jul 2008 04:34:56 -0000	1.29
--- bfd/vms-misc.c	17 Feb 2009 11:13:09 -0000
***************
*** 1,7 ****
! /* vms-misc.c -- Miscellaneous functions for 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.
  
     Written by Klaus K"ampf (kkaempf@rmi.de)
  
--- 1,9 ----
! /* 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, 2009  Free Software Foundation, Inc.
! 
!    Miscellaneous functions.
  
     Written by Klaus K"ampf (kkaempf@rmi.de)
  
***************
*** 30,51 ****
  #include "libbfd.h"
  
  #include "vms.h"
! 
  #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
  
!    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
     if level > 0.  */
  
  void
--- 32,60 ----
  #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:
  
!    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
     if level > 0.  */
  
  void
***************
*** 167,188 ****
  
  /* Object file input functions.  */
  
! /* Return type and length from record header (buf) on Alpha.  */
  
  void
  _bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
  			    unsigned char *buf,
  			    int *type,
! 			    int *length)
  {
!   if (type != 0)
      *type = bfd_getl16 (buf);
!   buf += 2;
!   if (length != 0)
!     *length = bfd_getl16 (buf);
  
  #if VMS_DEBUG
!   vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
  #endif
  }
  
--- 176,198 ----
  
  /* Object file input functions.  */
  
! /* 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 *size)
  {
!   if (type)
      *type = bfd_getl16 (buf);
! 
!   if (size)
!     *size = bfd_getl16 (buf+2);
  
  #if VMS_DEBUG
!   vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
! 	     type ? *type : 0, size ? *size : 0);
  #endif
  }
  
***************
*** 193,429 ****
  
     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.
  
!    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.
  
!    The vms format repeats the length 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
     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.
  
!    All file i/o is always done on even file positions.  */
  
  int
! _bfd_vms_get_record (bfd * abfd)
  {
!   int test_len, test_start, remaining;
!   unsigned char *vms_buf;
  
  #if VMS_DEBUG
!   vms_debug (8, "_bfd_vms_get_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 (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);
        PRIV (buf_size) = amt;
      }
  
!   vms_buf = PRIV (vms_buf);
  
!   if (vms_buf == 0)
!     return -1;
! 
!   switch (PRIV (file_format))
      {
!     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;
      }
  
!   /* Skip odd alignment byte.  */
  
!   if (bfd_tell (abfd) & 1)
      {
!       if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1)
! 	{
! 	  bfd_set_error (bfd_error_file_truncated);
! 	  return 0;
! 	}
      }
  
!   /* 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))
      {
!       bfd_set_error (bfd_error_file_truncated);
!       return 0;
      }
  
!   /* 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])
  	{
! 	  PRIV (file_format) = FF_FOREIGN;	/* Y: foreign environment.  */
! 	  test_start = 2;
  	}
!       else
  	{
! 	  PRIV (file_format) = FF_NATIVE;	/* N: native environment.  */
! 	  test_start = 0;
  	}
      }
  
    if (PRIV (is_vax))
      {
!       PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size),
! 				     abfd);
!       if (PRIV (rec_length) <= 0)
  	{
  	  bfd_set_error (bfd_error_file_truncated);
  	  return 0;
  	}
!       PRIV (vms_rec) = vms_buf;
      }
    else
      {
!       /* Alpha.   */
!       /* Extract vms record length.  */
  
!       _bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL,
! 				  & PRIV (rec_length));
  
!       if (PRIV (rec_length) <= 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)
  	{
  	  bfd_set_error (bfd_error_file_truncated);
  	  return 0;
  	}
  
!       /* Adjust the buffer.  */
  
!       if (PRIV (rec_length) > 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);
  	}
  
        /* Read the remaining record.  */
!       remaining = PRIV (rec_length) - test_len + test_start;
  
  #if VMS_DEBUG
!       vms_debug (10, "bfd_bread remaining %d\n", remaining);
  #endif
!       if (bfd_bread (vms_buf + test_len, (bfd_size_type) remaining, abfd) !=
! 	  (bfd_size_type) remaining)
  	{
  	  bfd_set_error (bfd_error_file_truncated);
  	  return 0;
  	}
!       PRIV (vms_rec) = vms_buf + test_start;
      }
  
  #if VMS_DEBUG
!   vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length));
  #endif
  
!   return PRIV (rec_length);
  }
  
! /* Get next vms record from file
!    update vms_rec and rec_length to new (remaining) values.  */
  
! int
! _bfd_vms_next_record (bfd * abfd)
  {
! #if VMS_DEBUG
!   vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
! 	      PRIV (rec_length), PRIV (rec_size));
! #endif
  
!   if (PRIV (rec_length) > 0)
!     PRIV (vms_rec) += PRIV (rec_size);
!   else
      {
!       if (_bfd_vms_get_record (abfd) <= 0)
! 	return -1;
      }
  
!   if (!PRIV (vms_rec) || !PRIV (vms_buf)
!       || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
!     return -1;
  
!   if (PRIV (is_vax))
      {
!       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));
  
!   PRIV (rec_length) -= PRIV (rec_size);
  
! #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
  
!   return PRIV (rec_type);
  }
! 
! /* Copy sized string (string with fixed length) to new allocated area
!    size is string length (size of record)  */
  
  char *
  _bfd_vms_save_sized_string (unsigned char *str, int size)
--- 203,543 ----
  
     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.
  
!    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 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 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
     environment where read() returns the record size (FF_NATIVE).
  
!    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.  */
! 
! #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_first_record (bfd *abfd)
  {
!   unsigned int test_len;
  
  #if VMS_DEBUG
!   vms_debug (8, "_bfd_vms_get_first_record\n");
  #endif
  
!   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)
      {
!       /* 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;
      }
  
!   /* Initialize the record pointer.  */
!   PRIV (vms_rec) = PRIV (vms_buf);
  
!   /* We only support modules on VAX.  */
!   if (PRIV (is_vax))
      {
!       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;
      }
  
!   if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
!     {
!       bfd_set_error (bfd_error_file_truncated);
!       return FT_UNKNOWN;
!     }
  
!   /* 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 (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;
      }
  
!   /* 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)
      {
!       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;
      }
  
! #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)
  	{
! 	  if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
! 	    {
! 	      bfd_set_error (bfd_error_file_truncated);
! 	      return -1;
! 	    }
  	}
! 
!       /* Read the record header  */
!       if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
  	{
! 	  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))
      {
!       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;
  	}
! 
!       /* Reset the record pointer.  */
!       PRIV (vms_rec) = PRIV (vms_buf);
      }
    else
      {
!       unsigned int to_read;
  
!       /* Extract record size.  */
!       PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
  
!       if (PRIV (rec_size) <= 0)
  	{
  	  bfd_set_error (bfd_error_file_truncated);
  	  return 0;
  	}
  
        /* That's what the linker manual says.  */
!       if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
  	{
  	  bfd_set_error (bfd_error_file_truncated);
  	  return 0;
  	}
  
!       /* Take into account object adjustment.  */
!       to_read = PRIV (rec_size);
!       if (PRIV (file_format) == FF_FOREIGN)
! 	to_read += VMS_OBJECT_ADJUSTMENT;
  
!       /* Adjust the buffer.  */
!       if (to_read > PRIV (buf_size))
  	{
! 	  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.  */
!       to_read -= read_so_far;
  
  #if VMS_DEBUG
!       vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
  #endif
! 
!       if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
  	{
  	  bfd_set_error (bfd_error_file_truncated);
  	  return 0;
  	}
! 
!       /* Reset the record pointer.  */
!       PRIV (vms_rec) = PRIV (vms_buf);
!       maybe_adjust_record_pointer_for_object (abfd);
      }
  
  #if VMS_DEBUG
!   vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
  #endif
  
!   return PRIV (rec_size);
  }
  
! /* Implement step #2 of the record reading procedure for images.
!    Return the size of the record or 0 on failure.  */
  
! static int
! vms_get_remaining_image_record (bfd *abfd, int read_so_far)
  {
!   unsigned int to_read;
!   int remaining;
  
!   /* Extract record size.  */
!   PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
! 
!   if (PRIV (rec_size) > PRIV (buf_size))
      {
!       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);
      }
  
!   /* Read the remaining record.  */
!   remaining = PRIV (rec_size) - read_so_far;
!   to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
  
!   while (remaining > 0)
      {
!       if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
! 	{
! 	  bfd_set_error (bfd_error_file_truncated);
! 	  return 0;
! 	}
  
!       read_so_far += to_read;
!       remaining -= to_read;
  
!       /* 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);
!     }
! 
!   /* Reset the record pointer.  */
!   PRIV (vms_rec) = PRIV (vms_buf);
  
!   return PRIV (rec_size);
  }
! 
! /* 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,445 ****
    return newstr;
  }
  
! /* Copy counted string (string with length at first byte) to new allocated area
!    ptr points to length byte on entry  */
  
  char *
  _bfd_vms_save_counted_string (unsigned char *ptr)
--- 552,559 ----
    return newstr;
  }
  
! /* 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,583 ****
    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).   */
  
  void
  _bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
--- 615,626 ----
    return value;
  }
  
  /* 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).  */
  
  void
  _bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
***************
*** 691,708 ****
  
    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 ();
! 
        PRIV (output_size) = 0;
      }
    else
--- 734,744 ----
  
    if (PRIV (push_level) == 0)
      {
!       /* 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,954 ****
    if (symbol == 0)
      return symbol;
    symbol->name = name;
!   symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
  
    return symbol;
  }
--- 984,990 ----
    if (symbol == 0)
      return symbol;
    symbol->name = name;
!   symbol->section = (asection *)(unsigned long)-1;
  
    return symbol;
  }
Index: bfd/vms-tir.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-tir.c,v
retrieving revision 1.20
diff -c -r1.20 vms-tir.c
*** bfd/vms-tir.c	20 Feb 2008 17:42:36 -0000	1.20
--- bfd/vms-tir.c	17 Feb 2009 11:13:10 -0000
***************
*** 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.
  
     TIR record handling functions
     ETIR 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)
--- 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, 2009 Free Software Foundation, Inc.
  
     TIR record handling functions
     ETIR 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)
***************
*** 26,32 ****
     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)
--- 26,31 ----
***************
*** 41,46 ****
--- 40,72 ----
  #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,97 ****
--- 118,194 ----
    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,114 ****
--- 206,214 ----
    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,130 ****
--- 225,233 ----
    if (PRIV (is_vax) && check_section (abfd, 1))
      return;
  
+   if (PRIV (dst_section))
+     dst_check_allocation (abfd, 1);
+ 
    *PRIV (image_ptr)++ = (value & 0xff);
  }
  
***************
*** 140,145 ****
--- 243,251 ----
    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,161 ****
--- 262,270 ----
    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,177 ****
--- 281,289 ----
    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,187 ****
--- 294,301 ----
    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,201 ****
--- 306,321 ----
      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,248 ****
      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";
  
      default:
        /* These names have not yet been added to this switch statement.  */
!       abort ();
      }
  }
  #define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
  
  /* etir_sta
  
!    vms stack commands
  
!    handle sta_xxx commands in etir section
!    ptr points to data area in record
  
!    see table B-8 of the openVMS linker manual.  */
  
  static bfd_boolean
! etir_sta (bfd * abfd, int cmd, unsigned char *ptr)
  {
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_sta %d/%x\n", cmd, cmd);
!   _bfd_hexdump (8, ptr, 16, (int) ptr);
  #endif
  
    switch (cmd)
      {
!       /* stack global
  	 arg: cs	symbol name
  
  	 stack 32 bit value of symbol (high bits set to 0).  */
--- 335,375 ----
      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.  */
!       (*_bfd_error_handler) (_("unknown ETIR command %d"), cmd);
      }
+ 
+   return NULL;
  }
  #define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
  
  /* etir_sta
  
!    Vms stack commands.
  
!    Handle sta_xxx commands in etir section,
!    ptr points to data area in record.
  
!    See table B-8 of the openVMS linker manual.  */
  
  static bfd_boolean
! 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, (long) ptr);
  #endif
  
    switch (cmd)
      {
!       /* Stack global
  	 arg: cs	symbol name
  
  	 stack 32 bit value of symbol (high bits set to 0).  */
***************
*** 265,301 ****
  	else
  	  _bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1);
        }
        break;
  
!       /* 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);
        break;
  
!       /* stack global
  	 arg: qw	value
  
  	 stack 64 bit value of symbol.  */
      case ETIR_S_C_STA_QW:
        _bfd_vms_push (abfd, (uquad) bfd_getl64 (ptr), -1);
        break;
  
!       /* stack psect base plus quadword offset
  	 arg: lw	section index
  	 qw	signed quadword offset (low 32 bits)
  
! 	 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;
  
  	psect = bfd_getl32 (ptr);
! 	if (psect >= PRIV (section_count))
  	  {
  	    (*_bfd_error_handler) (_("bad section index in %s"),
  				   cmd_name (cmd));
--- 392,441 ----
  	else
  	  _bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1);
        }
+       *quarter_relocs = 1;
        break;
  
!       /* 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 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
  	 arg: lw	section index
  	 qw	signed quadword offset (low 32 bits)
  
! 	 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;
! 	int psect;
  
  	psect = bfd_getl32 (ptr);
! 	if ((unsigned int) psect >= PRIV (section_count))
  	  {
  	    (*_bfd_error_handler) (_("bad section index in %s"),
  				   cmd_name (cmd));
***************
*** 305,327 ****
  	dummy = bfd_getl64 (ptr + 4);
  	_bfd_vms_push (abfd, dummy, (int) psect);
        }
        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));
        return FALSE;
-       break;
  
      default:
        (*_bfd_error_handler) (_("reserved STA cmd %d"), cmd);
        return FALSE;
-       break;
      }
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_sta true\n");
  #endif
    return TRUE;
  }
  
--- 445,475 ----
  	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;
  
      default:
        (*_bfd_error_handler) (_("reserved STA cmd %d"), cmd);
+       *quarter_relocs = 0;
        return FALSE;
      }
+ 
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_sta true\n");
  #endif
+ 
    return TRUE;
  }
  
***************
*** 335,348 ****
     see table B-9 of the openVMS linker manual.  */
  
  static bfd_boolean
! etir_sto (bfd * abfd, int cmd, unsigned char *ptr)
  {
    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);
  #endif
  
    switch (cmd)
--- 483,496 ----
     see table B-9 of the openVMS linker manual.  */
  
  static bfd_boolean
! 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, (long) ptr);
  #endif
  
    switch (cmd)
***************
*** 353,358 ****
--- 501,507 ----
        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,366 ****
--- 510,516 ----
        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,375 ****
--- 520,529 ----
        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,384 ****
--- 533,542 ----
        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,398 ****
--- 551,557 ----
  	while (dummy-- > 0)
  	  image_dump (abfd, ptr+4, size, 0);
        }
+       *quarter_relocs = 0;
        break;
  
        /* Store global: write symbol value
***************
*** 406,420 ****
  	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;
! 	  }
  	else
  	  /* FIXME, reloc.  */
  	  image_write_q (abfd, (uquad) (entry->symbol->value));
        }
        break;
  
        /* Store code address: write address of entry point
--- 565,577 ----
  	entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
  						      name, FALSE, FALSE);
  	if (entry == NULL)
! 	  /* 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,442 ****
  	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;
! 	  }
  	else
  	  /* FIXME, reloc.  */
  	  image_write_q (abfd, (uquad) (entry->symbol->value));
        }
        break;
  
        /* Store offset to psect: pop stack, add low 32 bits to base of psect
--- 585,597 ----
  	entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
  						      name, FALSE, FALSE);
  	if (entry == NULL)
! 	  /* 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,455 ****
--- 605,611 ----
  	q += (PRIV (sections)[psect1])->vma;
  	image_write_q (abfd, q);
        }
+       *quarter_relocs += 2;
        break;
  
        /* Store immediate
***************
*** 462,467 ****
--- 618,624 ----
  	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,510 ****
  	  /* FIXME, reloc.  */
  	  image_write_l (abfd, (unsigned long) (entry->symbol->value));
        }
        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;
  
      case ETIR_S_C_STO_HINT_GBL:
      case ETIR_S_C_STO_HINT_PS:
        (*_bfd_error_handler) (_("%s: not implemented"), cmd_name (cmd));
!       break;
  
      default:
        (*_bfd_error_handler) (_("reserved STO cmd %d"), cmd);
!       break;
      }
  
    return TRUE;
--- 646,671 ----
  	  /* 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));
!       *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));
!       *quarter_relocs = 0;
!       return FALSE;
  
      default:
        (*_bfd_error_handler) (_("reserved STO cmd %d"), cmd);
!       *quarter_relocs = 0;
!       return FALSE;
      }
  
    return TRUE;
***************
*** 518,532 ****
     see table B-10 of the openVMS linker manual.  */
  
  static bfd_boolean
! etir_opr (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED)
  {
    long op1, op2;
  
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_opr %d/%x\n", cmd, cmd);
!   _bfd_hexdump (8, ptr, 16, (int) ptr);
  #endif
  
    switch (cmd)
      {
      case ETIR_S_C_OPR_NOP:      /* No-op.  */
--- 679,700 ----
     see table B-10 of the openVMS linker manual.  */
  
  static bfd_boolean
! 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, (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,610 ****
      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;
  
      case ETIR_S_C_OPR_SEL:      /* Select.  */
        if ((long) _bfd_vms_pop (abfd, NULL) & 0x01L)
--- 772,778 ----
      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));
!       return FALSE;
  
      case ETIR_S_C_OPR_SEL:      /* Select.  */
        if ((long) _bfd_vms_pop (abfd, NULL) & 0x01L)
***************
*** 619,625 ****
  
      default:
        (*_bfd_error_handler) (_("reserved OPR cmd %d"), cmd);
!       break;
      }
  
    return TRUE;
--- 787,793 ----
  
      default:
        (*_bfd_error_handler) (_("reserved OPR cmd %d"), cmd);
!       return FALSE;
      }
  
    return TRUE;
***************
*** 630,645 ****
     See table B-11 of the openVMS linker manual.  */
  
  static bfd_boolean
! etir_ctl (bfd * abfd, int cmd, unsigned char *ptr)
  {
!   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);
  #endif
  
    switch (cmd)
      {
        /* Det relocation base: pop stack, set image location counter
--- 798,816 ----
     See table B-11 of the openVMS linker manual.  */
  
  static bfd_boolean
! etir_ctl (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
  {
!   uquad dummy;
    int psect;
  
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_ctl %d/%x\n", cmd, cmd);
!   _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,686 ****
  	 arg: none.  */
      case ETIR_S_C_CTL_DFLOC:
        dummy = _bfd_vms_pop (abfd, NULL);
!       /* FIXME */
        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 */
        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.  */
        break;
  
      default:
        (*_bfd_error_handler) (_("reserved CTL cmd %d"), cmd);
!       break;
      }
    return TRUE;
  }
  
--- 831,858 ----
  	 arg: none.  */
      case ETIR_S_C_CTL_DFLOC:
        dummy = _bfd_vms_pop (abfd, NULL);
!       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, 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, NULL);
!       _bfd_vms_push (abfd, dst_retrieve_location (abfd, dummy), -1);
        break;
  
      default:
        (*_bfd_error_handler) (_("reserved CTL cmd %d"), cmd);
!       return FALSE;
      }
+ 
    return TRUE;
  }
  
***************
*** 689,699 ****
     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)
  {
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_stc %d/%x\n", cmd, cmd);
!   _bfd_hexdump (8, ptr, 16, (int) ptr);
  #endif
  
    switch (cmd)
--- 861,872 ----
     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,
! 	  int *quarter_relocs)
  {
  #if VMS_DEBUG
    _bfd_vms_debug (5, "etir_stc %d/%x\n", cmd, cmd);
!   _bfd_hexdump (8, ptr, 16, (long) ptr);
  #endif
  
    switch (cmd)
***************
*** 701,732 ****
        /* 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
--- 874,890 ----
***************
*** 734,789 ****
  		qw	offset.  */
      case ETIR_S_C_STC_PS:
        (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd));
        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:
  
        /* 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:
  
        /* 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:
  
        /* 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:
  
        /* 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
  	 arg: none.  */
      case ETIR_S_C_STC_NBH_PS:
!       /* FIXME */
!       break;
  
      default:
! #if VMS_DEBUG
!       _bfd_vms_debug (3,  "reserved STC cmd %d", cmd);
! #endif
!       break;
      }
    return TRUE;
  }
  
--- 892,973 ----
  		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:
!       /* ALPHA_R_NOP */
  
        /* 207 Store-conditional BSR at global address
  	 arg: none.  */
  
!     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:
!       /* ALPHA_R_LDA */
  
        /* 211 Store-conditional BSR or Hint at global address
  	 arg: none.  */
  
!     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:
  
!       /* 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:
!       (*_bfd_error_handler) ("%s: not supported", cmd_name (cmd));
!       *quarter_relocs = 0;
!       return FALSE;
  
      default:
!       (*_bfd_error_handler) (_("reserved STC cmd %d"), cmd);
!       *quarter_relocs = 0;
!       return FALSE;
      }
+ 
    return TRUE;
  }
  
***************
*** 851,860 ****
  
  /* tir_sta
  
!    vax stack commands
  
!    Handle sta_xxx commands in tir section
!    ptr points to data area in record
  
     See table 7-3 of the VAX/VMS linker manual.  */
  
--- 1035,1044 ----
  
  /* tir_sta
  
!    Vax stack commands.
  
!    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,930 ****
  		by	signed byte offset.  */
        {
  	unsigned long dummy;
! 	unsigned int psect;
  
  	if (cmd == TIR_S_C_STA_PB)
  	  psect = *ptr++;
--- 1108,1114 ----
  		by	signed byte offset.  */
        {
  	unsigned long dummy;
! 	int psect;
  
  	if (cmd == TIR_S_C_STA_PB)
  	  psect = *ptr++;
***************
*** 934,945 ****
  	    ptr += 2;
  	  }
  
! 	if (psect >= PRIV (section_count))
  	  alloc_section (abfd, psect);
  
  	dummy = (long) *ptr++;
  	dummy += (PRIV (sections)[psect])->vma;
! 	_bfd_vms_push (abfd, (uquad) dummy, (int) psect);
        }
        break;
  
--- 1118,1129 ----
  	    ptr += 2;
  	  }
  
! 	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, psect);
        }
        break;
  
***************
*** 951,957 ****
  		sh	signed short offset.  */
        {
  	unsigned long dummy;
! 	unsigned int psect;
  
  	if (cmd == TIR_S_C_STA_PW)
  	  psect = *ptr++;
--- 1135,1141 ----
  		sh	signed short offset.  */
        {
  	unsigned long dummy;
! 	int psect;
  
  	if (cmd == TIR_S_C_STA_PW)
  	  psect = *ptr++;
***************
*** 961,972 ****
  	    ptr += 2;
  	  }
  
! 	if (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);
        }
        break;
  
--- 1145,1156 ----
  	    ptr += 2;
  	  }
  
! 	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, psect);
        }
        break;
  
***************
*** 978,984 ****
  		lw	signed longword offset.	 */
        {
  	unsigned long dummy;
! 	unsigned int psect;
  
  	if (cmd == TIR_S_C_STA_PL)
  	  psect = *ptr++;
--- 1162,1168 ----
  		lw	signed longword offset.	 */
        {
  	unsigned long dummy;
! 	int psect;
  
  	if (cmd == TIR_S_C_STA_PL)
  	  psect = *ptr++;
***************
*** 988,999 ****
  	    ptr += 2;
  	  }
  
! 	if (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);
        }
        break;
  
--- 1172,1183 ----
  	    ptr += 2;
  	  }
  
! 	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, psect);
        }
        break;
  
***************
*** 1457,1463 ****
  tir_ctl (bfd * abfd, unsigned char *ptr)
  {
    unsigned long dummy;
!   unsigned int psect;
  
  #if VMS_DEBUG
    _bfd_vms_debug (5, "tir_ctl %d\n", *ptr);
--- 1641,1647 ----
  tir_ctl (bfd * abfd, unsigned char *ptr)
  {
    unsigned long dummy;
!   int psect;
  
  #if VMS_DEBUG
    _bfd_vms_debug (5, "tir_ctl %d\n", *ptr);
***************
*** 1468,1477 ****
      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))
  	alloc_section (abfd, psect);
!       image_set_ptr (abfd, (int) psect, (uquad) dummy);
        break;
  
      case TIR_S_C_CTL_AUGRB:
--- 1652,1661 ----
      case TIR_S_C_CTL_SETRB:
        /* Set relocation base: pop stack, set image location counter
  	 arg: none.  */
!       dummy = _bfd_vms_pop (abfd, &psect);
!       if ((unsigned int) psect >= PRIV (section_count))
  	alloc_section (abfd, psect);
!       image_set_ptr (abfd, psect, (uquad) dummy);
        break;
  
      case TIR_S_C_CTL_AUGRB:
***************
*** 1492,1498 ****
      case TIR_S_C_CTL_STLOC:
        /* Set location: pop index, restore location counter from index
  	 arg: none.  */
!       dummy = _bfd_vms_pop (abfd, (int *) &psect);
        (*_bfd_error_handler) (_("%s: not fully implemented"),
  			     tir_cmd_name (ptr[-1]));
        break;
--- 1676,1682 ----
      case TIR_S_C_CTL_STLOC:
        /* Set location: pop index, restore location counter from index
  	 arg: none.  */
!       dummy = _bfd_vms_pop (abfd, &psect);
        (*_bfd_error_handler) (_("%s: not fully implemented"),
  			     tir_cmd_name (ptr[-1]));
        break;
***************
*** 1500,1506 ****
      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);
        (*_bfd_error_handler) (_("%s: not fully implemented"),
  			     tir_cmd_name (ptr[-1]));
        break;
--- 1684,1690 ----
      case TIR_S_C_CTL_STKDL:
        /* Stack defined location: pop index, push location counter from index
  	 arg: none.  */
!       dummy = _bfd_vms_pop (abfd, &psect);
        (*_bfd_error_handler) (_("%s: not fully implemented"),
  			     tir_cmd_name (ptr[-1]));
        break;
***************
*** 1517,1523 ****
  static unsigned char *
  tir_cmd (bfd * abfd, unsigned char *ptr)
  {
!   struct
    {
      int mincod;
      int maxcod;
--- 1701,1707 ----
  static unsigned char *
  tir_cmd (bfd * abfd, unsigned char *ptr)
  {
!   static const struct
    {
      int mincod;
      int maxcod;
***************
*** 1535,1541 ****
  
  #if VMS_DEBUG
    _bfd_vms_debug (4, "tir_cmd %d/%x\n", *ptr, *ptr);
!   _bfd_hexdump (8, ptr, 16, (int) ptr);
  #endif
  
    if (*ptr & 0x80)
--- 1719,1725 ----
  
  #if VMS_DEBUG
    _bfd_vms_debug (4, "tir_cmd %d/%x\n", *ptr, *ptr);
!   _bfd_hexdump (8, ptr, 16, (long) ptr);
  #endif
  
    if (*ptr & 0x80)
***************
*** 1570,1582 ****
  /* Handle command from ETIR section.  */
  
  static int
! etir_cmd (bfd * abfd, int cmd, unsigned char *ptr)
  {
!   static struct
    {
      int mincod;
      int maxcod;
!     bfd_boolean (*explain) (bfd *, int, unsigned char *);
    }
    etir_table[] =
    {
--- 1754,1766 ----
  /* Handle command from ETIR section.  */
  
  static int
! etir_cmd (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
  {
!   static const struct
    {
      int mincod;
      int maxcod;
!     bfd_boolean (*explain) (bfd *, int, unsigned char *, int *);
    }
    etir_table[] =
    {
***************
*** 1591,1598 ****
    int i = 0;
  
  #if VMS_DEBUG
!   _bfd_vms_debug (4, "etir_cmd %d/%x\n", cmd, cmd);
!   _bfd_hexdump (8, ptr, 16, (int) ptr);
  #endif
  
    while (etir_table[i].mincod >= 0)
--- 1775,1782 ----
    int i = 0;
  
  #if VMS_DEBUG
!   _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,1606 ****
        if ( (etir_table[i].mincod <= cmd)
  	   && (cmd <= etir_table[i].maxcod))
  	{
! 	  if (!etir_table[i].explain (abfd, cmd, ptr))
  	    return -1;
  	  break;
  	}
--- 1784,1790 ----
        if ( (etir_table[i].mincod <= cmd)
  	   && (cmd <= etir_table[i].maxcod))
  	{
! 	  if (!etir_table[i].explain (abfd, cmd, ptr, quarter_relocs))
  	    return -1;
  	  break;
  	}
***************
*** 1608,1614 ****
      }
  
  #if VMS_DEBUG
!   _bfd_vms_debug (4, "etir_cmd: = 0\n");
  #endif
    return 0;
  }
--- 1792,1798 ----
      }
  
  #if VMS_DEBUG
!   _bfd_vms_debug (4, "etir_cmd: result = 0\n");
  #endif
    return 0;
  }
***************
*** 1643,1670 ****
  static int
  analyze_etir (bfd * abfd, unsigned char *ptr, unsigned int length)
  {
!   int cmd;
!   unsigned char *maxptr;
    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);
        if (result != 0)
  	break;
!       ptr += length;
      }
  
  #if VMS_DEBUG
!   _bfd_vms_debug (3, "analyze_etir: = %d\n", result);
  #endif
  
    return result;
--- 1827,1893 ----
  static int
  analyze_etir (bfd * abfd, unsigned char *ptr, unsigned int length)
  {
!   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
  
    while (ptr < maxptr)
      {
!       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;
! 
!       /* 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: result = %d\n", result);
  #endif
  
    return result;
***************
*** 1685,1692 ****
    switch (objtype)
      {
      case EOBJ_S_C_ETIR:
!       PRIV (vms_rec) += 4;	/* Skip type, size.  */
!       PRIV (rec_size) -= 4;
        result = analyze_etir (abfd, PRIV (vms_rec), (unsigned) PRIV (rec_size));
        break;
      case OBJ_S_C_TIR:
--- 1908,1915 ----
    switch (objtype)
      {
      case EOBJ_S_C_ETIR:
!       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,1734 ****
    return result;
  }
  
! /* Process EDBG record
!    Return 0 on success, -1 on error
! 
!    Not implemented yet.  */
  
  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 0;
  }
  
! /* Process ETBT record
!    Return 0 on success, -1 on error
! 
!    Not implemented yet.  */
  
  int
! _bfd_vms_slurp_tbt (bfd * abfd ATTRIBUTE_UNUSED,
! 		    int objtype ATTRIBUTE_UNUSED)
  {
  #if VMS_DEBUG
!   _bfd_vms_debug (2, "TBT/ETBT\n");
  #endif
  
    return 0;
--- 1925,2285 ----
    return result;
  }
  
!  /* Slurp relocs from ETIR sections and (temporarily) save them
!     in the per-section reloc buffer.  */
  
  int
! _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 (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
  
    return 0;
  }
  
! /* Decode relocs from the reloc buffer of the specified section
!    and internalize them in the specified buffer.  */
  
  int
! _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 (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,1755 ****
--- 2301,2320 ----
    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,1804 ****
    _bfd_vms_output_end (abfd);
  }
  
! /* WRITE ETIR SECTION
! 
!    This is still under construction and therefore not documented.  */
  
  static void
! sto_imm (bfd * abfd, vms_section *sptr, bfd_vma vaddr, int index)
  {
!   int size;
!   int ssize;
!   unsigned char *cptr;
  
  #if VMS_DEBUG
!   _bfd_vms_debug (8, "sto_imm %d bytes\n", sptr->size);
!   _bfd_hexdump (9, sptr->contents, (int) sptr->size, (int) vaddr);
  #endif
  
-   ssize = sptr->size;
-   cptr = sptr->contents;
- 
    while (ssize > 0)
      {
        /* Try all the rest.  */
--- 2345,2364 ----
    _bfd_vms_output_end (abfd);
  }
  
! /* 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, bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr,
! 	 int index, const char *name)
  {
!   bfd_size_type size;
  
  #if VMS_DEBUG
!   _bfd_vms_debug (8, "sto_imm %d bytes\n", ssize);
!   _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr);
  #endif
  
    while (ssize > 0)
      {
        /* Try all the rest.  */
***************
*** 1808,1818 ****
  	{
  	  /* 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)
  	    size = ssize;
  	}
  
--- 2368,2381 ----
  	{
  	  /* Doesn't fit, split !  */
  	  end_etir_record (abfd);
! 
! 	  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,1834 ****
  #endif
  
        vaddr += size;
-       ssize -= size;
        cptr += size;
      }
  }
  
--- 2390,2452 ----
  #endif
  
        vaddr += 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,1845 ****
  _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);
--- 2456,2461 ----
***************
*** 1847,2237 ****
  
    _bfd_vms_output_alignment (abfd, 4);
  
-   nextoffset = 0;
    PRIV (vms_linkage_index) = 1;
  
!   /* Dump all other sections.  */
!   section = abfd->sections;
! 
!   while (section != NULL)
      {
- 
  #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_RELOC)
  	{
! 	  int i;
  
- 	  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;
  	      _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",
  				  (*(*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++;
  		}
  	    }
  #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)
  	    {
! 	      bfd_set_error (bfd_error_no_contents);
! 	      return -1;
! 	    }
  
! 	  vaddr = (bfd_vma) (sptr->offset);
  
! 	  start_etir_record (abfd, section->index, (uquad) sptr->offset,
! 			     FALSE);
  
! 	  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;
  
! 		  for (;;)
  		    {
! 		      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)
! 			{
! 			  /* 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++;
! 			    }
  			}
  		      else
  			{
! 			  /* Sptr starts after reloc.  */
! 			  i--;
! 			  /* Check next reloc.  */
! 			  rptr++;
  			}
  
! 		      if (i == 0)
  			{
! 			  /* All reloc checked.  */
! 			  if (sptr->size > 0)
! 			    {
! 			      /* Dump rest.  */
! 			      sto_imm (abfd, sptr, vaddr, section->index);
! 			      vaddr += sptr->size;
! 			    }
! 			  break;
  			}
  		    }
  		}
! 	      else
  		{
! 		  /* No relocs, just dump.  */
! 		  sto_imm (abfd, sptr, vaddr, section->index);
! 		  vaddr += sptr->size;
  		}
- 
- 	      sptr = sptr->next;
  	    }
- 
- 	  end_etir_record (abfd);
  	}
  
!       section = section->next;
      }
  
    _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;
- }
--- 2463,2808 ----
  
    _bfd_vms_output_alignment (abfd, 4);
  
    PRIV (vms_linkage_index) = 1;
  
!   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)
  	{
! 	  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 VMS_DEBUG
  	  else
  	    {
! 	      int i = section->reloc_count;
! 	      arelent **rptr = section->orelocation;
  	      _bfd_vms_debug (4, "%d relocations:\n", i);
  	      while (i-- > 0)
  		{
! 		  _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++;
  		}
  	    }
  #endif
  
! 	new_pass:
! 	  for (irel = 0; irel < section->reloc_count; irel++)
  	    {
! 	      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;
! 		    }
  
! 		  /* 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;
! 		}
  
! 	      size = bfd_get_reloc_size (rptr->howto);
! 
! 	      switch (rptr->howto->type)
! 	        {
! 		case ALPHA_R_IGNORE:
! 		  break;
  
! 		case ALPHA_R_REFLONG:
! 		  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_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
  			{
! 			  _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;
  
! 		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
  			{
! 			  _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;
  		}
! 
! 	      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)
  		{
! 		  pass2_in_progress = 1;
! 		  goto new_pass;
  		}
  	    }
  	}
+   
+       else /* (section->flags & SEC_RELOC) */
+ 	sto_imm (abfd, section->size, section->contents, 0,
+ 		 section->index, section->name);
  
!       end_etir_record (abfd);
      }
  
    _bfd_vms_output_alignment (abfd, 2);
    return 0;
  }
Index: bfd/vms.c
===================================================================
RCS file: /cvs/src/src/bfd/vms.c,v
retrieving revision 1.45
diff -c -r1.45 vms.c
*** bfd/vms.c	20 Feb 2008 17:42:36 -0000	1.45
--- bfd/vms.c	17 Feb 2009 11:13:10 -0000
***************
*** 1,7 ****
  /* 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.
  
     Written by Klaus K"ampf (kkaempf@rmi.de)
  
--- 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, 2009 Free Software Foundation, Inc.
! 
!    Main file.
  
     Written by Klaus K"ampf (kkaempf@rmi.de)
  
***************
*** 20,25 ****
--- 22,34 ----
     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,32 ****
--- 36,143 ----
  
  #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,77 ****
  #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;
  extern const bfd_target vms_vax_vec;
  extern const bfd_target vms_alpha_vec;
- 
- /* 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);
    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;
    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);
--- 147,184 ----
  #define vms_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
  #define vms_get_synthetic_symtab          _bfd_nodynamic_get_synthetic_symtab
  
! 
! #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  */
  static bfd_boolean
  vms_initialize (bfd * abfd)
  {
    bfd_size_type amt;
  
    bfd_set_start_address (abfd, (bfd_vma) -1);
  
    amt = sizeof (struct vms_private_data_struct);
!   abfd->tdata.any = bfd_zalloc (abfd, amt);
    if (abfd->tdata.any == NULL)
      return FALSE;
  
!   if (bfd_get_flavour (abfd) == bfd_target_ovax_flavour)
!     PRIV (is_vax) = TRUE;
! 
    PRIV (file_format) = FF_UNKNOWN;
  
    amt = sizeof (struct stack_struct) * STACKSIZE;
    PRIV (stack) = bfd_alloc (abfd, amt);
    if (PRIV (stack) == NULL)
      goto error_ret1;
  
    amt = sizeof (struct bfd_hash_table);
    PRIV (vms_symbol_table) = bfd_alloc (abfd, amt);
***************
*** 82,105 ****
  			    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;
  
--- 189,200 ----
***************
*** 111,264 ****
    return FALSE;
  }
  
! /* Fill symbol->section with section ptr
     symbol->section is filled with the section index for defined symbols
!    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
  
!    called from bfd_hash_traverse in vms_fixup_sections.  */
  
  static bfd_boolean
! fill_section_ptr (struct bfd_hash_entry * entry, void * sections)
  {
!   asection *sec;
!   asymbol *sym;
! 
!   sym = ((vms_symbol_entry *) entry)->symbol;
!   sec = sym->section;
  
  #if 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;
  
    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).  */
! 
  static bfd_boolean
  vms_fixup_sections (bfd * abfd)
  {
    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)));
  
    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)
  {
!   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;
  
    do
      {
  #if VMS_DEBUG
        vms_debug (7, "reading at %08lx\n", bfd_tell (abfd));
  #endif
!       if (_bfd_vms_next_record (abfd) < 0)
  	{
  #if VMS_DEBUG
  	  vms_debug (2, "next_record failed\n");
  #endif
! 	  goto err_wrong_format;
  	}
  
!       if ((prev_type == EOBJ_S_C_EGSD)
! 	   && (PRIV (rec_type) != EOBJ_S_C_EGSD))
  	{
  	  if (! vms_fixup_sections (abfd))
  	    {
  #if VMS_DEBUG
  	      vms_debug (2, "vms_fixup_sections failed\n");
  #endif
! 	      goto err_wrong_format;
  	    }
  	}
  
!       prev_type = PRIV (rec_type);
! 
!       if (target_vector == NULL)
! 	{
! 	  if (prev_type <= OBJ_S_C_MAXRECTYP)
! 	    target_vector = & vms_vax_vec;
! 	  else
! 	    target_vector = & vms_alpha_vec;
! 	}
  
!       switch (prev_type)
  	{
  	  case OBJ_S_C_HDR:
  	  case EOBJ_S_C_EMH:
! 	    err = _bfd_vms_slurp_hdr (abfd, prev_type);
  	    break;
  	  case OBJ_S_C_EOM:
  	  case OBJ_S_C_EOMW:
  	  case EOBJ_S_C_EEOM:
! 	    err = _bfd_vms_slurp_eom (abfd, prev_type);
  	    break;
  	  case OBJ_S_C_GSD:
  	  case EOBJ_S_C_EGSD:
! 	    err = _bfd_vms_slurp_gsd (abfd, prev_type);
  	    break;
  	  case OBJ_S_C_TIR:
  	  case EOBJ_S_C_ETIR:
! 	    err = _bfd_vms_slurp_tir (abfd, prev_type);
  	    break;
  	  case OBJ_S_C_DBG:
  	  case EOBJ_S_C_EDBG:
! 	    err = _bfd_vms_slurp_dbg (abfd, prev_type);
  	    break;
  	  case OBJ_S_C_TBT:
  	  case EOBJ_S_C_ETBT:
! 	    err = _bfd_vms_slurp_tbt (abfd, prev_type);
  	    break;
  	  case OBJ_S_C_LNK:
! 	    err = _bfd_vms_slurp_lnk (abfd, prev_type);
  	    break;
  	  default:
  	    err = -1;
--- 206,332 ----
    return FALSE;
  }
  
! 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
     bfd section later.
  
!    It has the correct value for referenced (undefined section) symbols.
  
!    Called from bfd_hash_traverse in vms_fixup_sections.  */
  
  static bfd_boolean
! fill_section_ptr (struct bfd_hash_entry *entry, void *sections)
  {
!   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
  
!   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 section pointers in symbols.  */
  static bfd_boolean
  vms_fixup_sections (bfd * abfd)
  {
+   struct pair data;
+ 
    if (PRIV (fixup_done))
      return TRUE;
  
!   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;
  }
  
! /* Slurp an ordered set of VMS object records.  */
! int
! _bfd_vms_slurp_object_records (bfd * abfd)
  {
!   int err, new_type, type = -1;
  
    do
      {
  #if VMS_DEBUG
        vms_debug (7, "reading at %08lx\n", bfd_tell (abfd));
  #endif
!       new_type = _bfd_vms_get_object_record (abfd);
!       if (new_type < 0)
  	{
  #if VMS_DEBUG
  	  vms_debug (2, "next_record failed\n");
  #endif
! 	  return -1;
  	}
  
!       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
! 	      return -1;
  	    }
  	}
  
!       type = new_type;
  
!       switch (type)
  	{
  	  case OBJ_S_C_HDR:
  	  case EOBJ_S_C_EMH:
! 	    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, type);
  	    break;
  	  case OBJ_S_C_GSD:
  	  case EOBJ_S_C_EGSD:
! 	    err = _bfd_vms_slurp_gsd (abfd, type);
  	    break;
  	  case OBJ_S_C_TIR:
  	  case EOBJ_S_C_ETIR:
! 	    err = _bfd_vms_slurp_tir (abfd, type);
  	    break;
  	  case OBJ_S_C_DBG:
  	  case EOBJ_S_C_EDBG:
! 	    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, type);
! 	    PRIV (dst_ptr_end) = PRIV (image_ptr);
  	    break;
  	  case OBJ_S_C_LNK:
! 	    err = _bfd_vms_slurp_lnk (abfd, type);
  	    break;
  	  default:
  	    err = -1;
***************
*** 266,279 ****
        if (err != 0)
  	{
  #if VMS_DEBUG
! 	  vms_debug (2, "slurp type %d failed with %d\n", prev_type, err);
  #endif
! 	  goto err_wrong_format;
  	}
      }
!   while ((prev_type != EOBJ_S_C_EEOM) && (prev_type != OBJ_S_C_EOM) && (prev_type != OBJ_S_C_EOMW));
  
!   if (target_vector == & vms_vax_vec)
      {
        if (! vms_fixup_sections (abfd))
  	{
--- 334,438 ----
        if (err != 0)
  	{
  #if VMS_DEBUG
! 	  vms_debug (2, "slurp type %d failed with %d\n", type, err);
  #endif
! 	  return err;
  	}
      }
!   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;
!     }
! 
!   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,320 ****
  	  goto err_wrong_format;
  	}
  
!       /* Set arch_info to vax.  */
! 
        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)
      {
        /* Set arch_info to alpha.   */
! 
        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);
--- 442,470 ----
  	  goto err_wrong_format;
  	}
  
!       target_vector = &vms_vax_vec;
        arch = bfd_scan_arch ("vax");
! 
  #if VMS_DEBUG
        vms_debug (2, "arch is vax\n");
  #endif
      }
!   else
      {
        /* Set arch_info to alpha.   */
!       target_vector = &vms_alpha_vec;
        arch = bfd_scan_arch ("alpha");
  #if VMS_DEBUG
        vms_debug (2, "arch is alpha\n");
  #endif
      }
  
    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,346 ****
--- 491,498 ----
  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,367 ****
    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;
!   }
  
    return TRUE;
  }
  
--- 500,517 ----
    if (!vms_initialize (abfd))
      return FALSE;
  
!   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,425 ****
--- 570,631 ----
  
  /* 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,435 ****
  #if VMS_DEBUG
    vms_debug (1, "vms_close_and_cleanup (%p)\n", abfd);
  #endif
!   if (abfd == NULL
!       || abfd->tdata.any == NULL)
      return TRUE;
  
    if (PRIV (vms_buf) != NULL)
--- 634,640 ----
  #if VMS_DEBUG
    vms_debug (1, "vms_close_and_cleanup (%p)\n", abfd);
  #endif
!   if (abfd == NULL || abfd->tdata.any == NULL)
      return TRUE;
  
    if (PRIV (vms_buf) != NULL)
***************
*** 441,449 ****
--- 646,668 ----
    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,468 ****
--- 682,689 ----
  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,476 ****
    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);
  
    if (section_count > PRIV (section_count))
      {
--- 691,698 ----
    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, 0);
  
    if (section_count > PRIV (section_count))
      {
***************
*** 481,494 ****
--- 703,724 ----
  	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,515 ****
  			  file_ptr offset ATTRIBUTE_UNUSED,
  			  bfd_size_type buf_size ATTRIBUTE_UNUSED)
  {
  #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;
  }
  
  /* Read the contents of a section.
--- 733,774 ----
  			  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
  
!   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,709 ****
  #if VMS_DEBUG
    vms_debug (1, "vms_truncate_arname (%p, %s, %s)\n", abfd, pathname, arhdr);
  #endif
-   return;
  }
  
  /* ???	write archive map.  */
--- 962,967 ----
***************
*** 906,912 ****
    if (ret == NULL)
      return;
  
!   if (bfd_is_com_section (sec))
      ret->type = 'C';
    else if (bfd_is_abs_section (sec))
      ret->type = 'A';
--- 1164,1172 ----
    if (ret == NULL)
      return;
  
!   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,978 ****
    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;
  }
  
  static bfd_boolean
--- 1232,1238 ----
    vms_debug (1, "vms_find_nearest_line (%p, %s, %p, %ld, <ret>, <ret>, <ret>)\n",
  	      abfd, section->name, symbols, (long int)offset);
  #endif
!   return _bfd_vms_find_nearest_dst_line (abfd, section, symbols, offset, file, func, line);
  }
  
  static bfd_boolean
***************
*** 1037,1072 ****
  
  /* 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.  */
  
! static long
! vms_get_reloc_upper_bound (bfd * abfd ATTRIBUTE_UNUSED,
! 			   asection *section ATTRIBUTE_UNUSED)
  {
  #if VMS_DEBUG
!   vms_debug (1, "vms_get_reloc_upper_bound (%p, %s)\n", abfd, section->name);
  #endif
!   return -1L;
  }
  
! /* 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.  */
  
  static long
! vms_canonicalize_reloc (bfd * abfd ATTRIBUTE_UNUSED,
! 			asection *section ATTRIBUTE_UNUSED,
! 			arelent **location ATTRIBUTE_UNUSED,
! 			asymbol **symbols ATTRIBUTE_UNUSED)
  {
! #if VMS_DEBUG
!   vms_debug (1, "vms_canonicalize_reloc (%p, %s, <ret>, <ret>)\n", abfd, section->name);
! #endif
!   return FALSE;
  }
  
  /* This is just copied from ecoff-alpha, needs to be fixed probably.  */
--- 1297,1456 ----
  
  /* Part 4.6, relocations.  */
  
! /* Allocate the reloc buffer for the specified section.  */
  
! 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 (2, "decode relocs failed with %d\n", err);
! #endif
!       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;
  }
  
! /* Return the number of bytes required to store the relocation
!    information associated with the given section.  */
  
  static long
! vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
  {
!   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,1322 ****
--- 1701,1764 ----
  	 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,1350 ****
--- 1787,1796 ----
        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,1398 ****
  #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;
  }
  
  /* 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.
  
     Normally TRUE is returned, else FALSE. Possible error returns are:
     o bfd_error_no_contents - The output section does not have the
--- 1831,1848 ----
  #if VMS_DEBUG
    vms_debug (1, "vms_set_arch_mach (%p, %d, %ld)\n", abfd, arch, mach);
  #endif
  
!   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 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,1417 ****
  	     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);
  }
  
  /* Part 4.8, linker.  */
--- 1861,1876 ----
  	     abfd, section->name, location, (long int)offset, (int)count);
    vms_debug (2, "size %d\n", (int) section->size);
  #endif
!   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,1556 ****
  #if VMS_DEBUG
    vms_debug (1, "vms_get_dynamic_symtab_upper_bound (%p)\n", abfd);
  #endif
!   return 0;
  }
  
  static bfd_boolean
--- 2009,2015 ----
  #if VMS_DEBUG
    vms_debug (1, "vms_get_dynamic_symtab_upper_bound (%p)\n", abfd);
  #endif
!   return 0L;
  }
  
  static bfd_boolean
***************
*** 1601,1619 ****
  
  const bfd_target vms_alpha_vec =
  {
!   "vms-alpha",			/* Name.  */
    bfd_target_evax_flavour,
!   BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
!   BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
  
!   (HAS_RELOC | HAS_SYMS
!    | 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.  */
    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    bfd_getl16, bfd_getl_signed_16, bfd_putl16,
--- 2060,2078 ----
  
  const bfd_target vms_alpha_vec =
  {
!   "vms-alpha",			/* name */
    bfd_target_evax_flavour,
!   BFD_ENDIAN_LITTLE,		/* data byte order is little */
!   BFD_ENDIAN_LITTLE,		/* header byte order is little */
  
!   (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 */
    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    bfd_getl16, bfd_getl_signed_16, bfd_putl16,
***************
*** 1621,1631 ****
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    bfd_getl16, bfd_getl_signed_16, bfd_putl16,
  
!   {_bfd_dummy_target, vms_object_p,		/* bfd_check_format.  */
     vms_archive_p, _bfd_dummy_target},
!   {bfd_false, vms_mkobject,			/* bfd_set_format.  */
     _bfd_generic_mkarchive, bfd_false},
!   {bfd_false, vms_write_object_contents,	/* bfd_write_contents.  */
     _bfd_write_archive_contents, bfd_false},
  
    BFD_JUMP_TABLE_GENERIC (vms),
--- 2080,2090 ----
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    bfd_getl16, bfd_getl_signed_16, bfd_putl16,
  
!   {_bfd_dummy_target, vms_object_p,		/* bfd_check_format */
     vms_archive_p, _bfd_dummy_target},
!   {bfd_false, vms_mkobject,			/* bfd_set_format */
     _bfd_generic_mkarchive, bfd_false},
!   {bfd_false, vms_write_object_contents,	/* bfd_write_contents */
     _bfd_write_archive_contents, bfd_false},
  
    BFD_JUMP_TABLE_GENERIC (vms),
***************
*** 1640,1677 ****
  
    NULL,
  
!   NULL
  };
  
  const bfd_target vms_vax_vec =
  {
!   "vms-vax",			/* Name.  */
    bfd_target_ovax_flavour,
!   BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
!   BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
  
!   (HAS_RELOC | HAS_SYMS 	/* Object flags.  */
     | WP_TEXT | D_PAGED
     | HAS_LINENO | HAS_DEBUG | HAS_LOCALS),
  
    (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.  */
    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_dummy_target, vms_object_p,		/* bfd_check_format.  */
     vms_archive_p, _bfd_dummy_target},
!   {bfd_false, vms_mkobject,			/* bfd_set_format.  */
     _bfd_generic_mkarchive, bfd_false},
!   {bfd_false, vms_write_object_contents,	/* bfd_write_contents.  */
     _bfd_write_archive_contents, bfd_false},
  
    BFD_JUMP_TABLE_GENERIC (vms),
--- 2099,2136 ----
  
    NULL,
  
!   (PTR) 0
  };
  
  const bfd_target vms_vax_vec =
  {
!   "vms-vax",			/* name */
    bfd_target_ovax_flavour,
!   BFD_ENDIAN_LITTLE,		/* data byte order is little */
!   BFD_ENDIAN_LITTLE,		/* header byte order is little */
  
!   (HAS_RELOC | HAS_SYMS 	/* object flags */
     | WP_TEXT | D_PAGED
     | HAS_LINENO | HAS_DEBUG | HAS_LOCALS),
  
    (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 */
    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, /* hdrs */
  
!   {_bfd_dummy_target, vms_object_p,		/* bfd_check_format */
     vms_archive_p, _bfd_dummy_target},
!   {bfd_false, vms_mkobject,			/* bfd_set_format */
     _bfd_generic_mkarchive, bfd_false},
!   {bfd_false, vms_write_object_contents,	/* bfd_write_contents */
     _bfd_write_archive_contents, bfd_false},
  
    BFD_JUMP_TABLE_GENERIC (vms),
***************
*** 1686,1690 ****
  
    NULL,
  
!   NULL
  };
--- 2145,2149 ----
  
    NULL,
  
!   (PTR) 0
  };
Index: bfd/vms.h
===================================================================
RCS file: /cvs/src/src/bfd/vms.h,v
retrieving revision 1.13
diff -c -r1.13 vms.h
*** bfd/vms.h	3 Jul 2007 14:26:43 -0000	1.13
--- bfd/vms.h	17 Feb 2009 11:13:10 -0000
***************
*** 1,6 ****
  /* 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.
  
     Written by Klaus K"ampf (kkaempf@rmi.de)
  
--- 1,8 ----
  /* vms.h -- Header file for VMS (Alpha and Vax) support.
!    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,33 ****
  #ifndef VMS_H
  #define VMS_H
  
! /* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object language)  */
  
! /* VMS Text, information and relocation record (TIR/ETIR) definitions.  */
  
  #define TIR_S_C_STA_GBL		0
  #define TIR_S_C_STA_SB		1
--- 27,38 ----
  #ifndef VMS_H
  #define VMS_H
  
! /* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object
!    language).  */
! 
! #define VMS_BLOCK_SIZE  512
  
! /* VMS Text Information and Relocation Records (TIR/ETIR).  */
  
  #define TIR_S_C_STA_GBL		0
  #define TIR_S_C_STA_SB		1
***************
*** 107,113 ****
  #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_LI 4		/* Stack literal.		*/
  #define ETIR_S_C_STA_MOD 5		/* Stack module.		*/
  #define ETIR_S_C_STA_CKARG 6		/* Check Arguments.		*/
--- 112,118 ----
  #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 + 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,179 ****
  #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 GSD_S_K_ENTRIES 1
  #define GSD_S_C_ENTRIES 1
--- 178,186 ----
  #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.   */
  
! #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,211 ****
--- 213,219 ----
  #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,249 ****
  #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 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 LSY_S_M_DEF     2
  #define LSY_S_M_REL     8
--- 227,267 ----
  #define GPS_S_K_NAME    9
  #define GPS_S_C_NAME    9
  
! #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_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,260 ****
--- 269,294 ----
  #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,283 ****
  #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
  #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_SET_PC		10
  #define DST_S_C_SET_PC_W	11
  #define DST_S_C_SET_PC_L	12
--- 303,321 ----
  #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.	*/
! 
! /* 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_SET_PC		10
  #define DST_S_C_SET_PC_W	11
  #define DST_S_C_SET_PC_L	12
***************
*** 295,303 ****
--- 333,364 ----
  #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,333 ****
--- 389,395 ----
  #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,342 ****
  #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.  */
  /* 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.  */
--- 398,404 ----
  #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.  */
  /* 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,385 ****
  #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.  */
  
  #define MHD_S_C_MHD 0
  #define MHD_S_C_LNM 1
--- 441,447 ----
  #define DBG_S_C_VOID			DST_K_TS_PTR
  #define DBG_S_C_COMPLEX_ARRAY		DST_K_TS_ARRAY
  
! /* VMS Module Header Records (MHD/EMH).  */
  
  #define MHD_S_C_MHD 0
  #define MHD_S_C_LNM 1
***************
*** 402,449 ****
  /* vms.c.  */
  
  extern asymbol *_bfd_vms_make_empty_symbol (bfd *);
  
  /* vms-gsd.c.  */
  
! extern int _bfd_vms_slurp_gsd (bfd *, int);
! extern int _bfd_vms_write_gsd (bfd *, int);
  
! /* vms-mhd.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);
  
! /* 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.  */	 
- 					 
  #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.		*/
--- 464,531 ----
  /* 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 *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-misc.c.  */
! 
! 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 *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,465 ****
  #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_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		 
--- 535,549 ----
  #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_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,482 ****
  #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__				 
--- 559,567 ----
  #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,623 ****
  #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;				 
! 					 
  /* 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;			 
! 					 
  /* 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;				 
    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];
! 					 
    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
! 					 
  #define SECTION_NAME_TEMPLATE "__SEC__%d"
  					 
  #if VMS_DEBUG				 
--- 569,854 ----
  #else					 
  typedef unsigned long uquad;		 
  #endif					 
! 
! #define MAX_OUTREC_SIZE 4096
! #define MIN_OUTREC_LUFT 64
! 
  /* VMS module header.  */		 
! 
! 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
! 
! /* 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;		/* 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;
! 
!   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,641 ****
  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 *);
--- 866,871 ----
***************
*** 653,656 ****
--- 883,889 ----
  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 */


More information about the Binutils mailing list