* vms.h: Update copyright year, fix comments, reorder declarations.
(_bfd_save_vms_section): Remove the prototype.
(EGPS_S_V_NO_SHIFT): New constant.
(bfd_vms_set_section_flags): New prototype.
(EGPS_S_B_ALIGN, EGPS_S_W_FLAGS, EGPS_S_L_ALLOC, EGPS_S_B_NAMLNG): New
constants.
(EGSY_S_W_FLAGS): Ditto.
(EGSY_S_V_QUAD_VAL): Ditto.
(ESDF_S_L_VALUE, ESDF_S_L_PSINDX, ESDF_S_B_NAMLNG): Ditto.
(EGST_S_W_FLAGS, EGST_S_Q_LP_1, EGST_S_Q_LP_2, EGST_S_L_PSINDX,
EGST_S_B_NAMLNG): Ditto.
(ESRF_S_B_NAMLNG): Ditto.
(ETIR_S_C_HEADER_SIZE): Ditto.
(EGPS_S_V_ALLOC_64BIT): Ditto.
(DST_S_C_EPILOG): Ditto.
(DST_S_C_SRC_SETLNUM_L, DST_S_C_SRC_SETLNUM_W) : Ditto.
(DST_S_C_SRC_INCRLNUM_B): Ditto.
(DST_S_B_PCLINE_UNSBYTE, DST_S_W_PCLINE_UNSWORD): Ditto.
(DST_S_L_PCLINE_UNSLONG): Ditto.
(DST_S_B_MODBEG_NAME, DST_S_L_RTNBEG_ADDRESS) : Ditto
(DST_S_B_RTNBEG_NAME, DST_S_L_RTNEND_SIZE): Ditto
(DST_S_C_SOURCE_HEADER_SIZE): Ditto.
(DST_S_B_SRC_DF_LENGTH, DST_S_W_SRC_DF_FILEID): Ditto.
(DST_S_B_SRC_DF_FILENAME, DST_S_B_SRC_UNSBYTE): Ditto.
(DST_S_B_SRC_UNSBYTE): Ditto.
(DST_S_W_SRC_UNSWORD, DST_S_L_SRC_UNSLONG): Ditto.
Add prototypes.
(vms_section, vms_reloc): Remove types.
(hdr_struc): Replaced by ...
(hdr_struct): ... new type.
(EMH_S_W_HDRTYP, EMH_S_B_STRLVL, EMH_S_L_ARCH1): New constants.
(EMH_S_L_ARCH2, EMH_S_L_RECSIZ, EMH_S_B_NAMLNG): Ditto.
(EMH_DATE_LENGTH): Ditto.
(eom_struc): Replaced by ...
(eom_struct): ... new type.
(EEOM_S_L_TOTAL_LPS, EEOM_S_W_COMCOD, EEOM_S_B_TFRFLG): New constants.
(EEOM_S_L_PSINDX, EEOM_S_L_TFRADR): Ditto.
(EIHD_S_K_MAJORID, EIHD_S_K_MINORID, EIHD_S_K_EXE): Ditto.
(EIHD_S_L_SIZE, EIHD_S_L_ISDOFF, EIHD_S_L_SYMDBGOFF): Ditto.
(EIHD_S_Q_SYMVVA, EIHD_S_L_IMGTYPE): Ditto.
(EISD_S_L_EISDSIZE, EISD_S_L_SECSIZE, EISD_S_Q_VIR_ADDR): Ditto.
(EISD_S_L_FLAGS, EISD_S_L_VBN, EISD_S_R_CONTROL): Ditto.
(EISD_S_L_IDENT, EISD_S_T_GBLNAM): Ditto.
(EISD_S_M_GBL, EISD_S_M_CRF, EISD_S_M_DZRO, EISD_S_M_WRT): Ditto.
(EISD_S_M_INITALCODE, EISD_S_M_BASED, EISD_S_M_FIXUPVEC): Ditto.
(EISD_S_M_RESIDENT, EISD_S_M_VECTOR, EISD_S_M_PROTECT): Ditto.
(EISD_S_M_LASTCLU, EISD_S_M_EXE, EISD_S_M_NONSHRADR): Ditto.
(EISD_S_M_QUAD_LENGTH, EISD_S_M_ALLOC_64BIT): Ditto.
(EIHS_S_L_DSTVBN, EIHS_S_L_DSTSIZE, EIHS_S_L_GSTVBN): Ditto.
(EIHS_S_L_GSTSIZE, EIHS_S_L_DMTVBN, EIHS_S_L_DMTBYTES): Ditto.
(DBG_S_L_DMT_MODBEG, DBG_S_L_DST_SIZE): Ditto.
(DBG_S_W_DMT_PSECT_COUNT, DBG_S_C_DMT_HEADER_SIZE): Ditto.
(DBG_S_L_DMT_PSECT_START, DBG_S_L_DMT_PSECT_LENGTH)
(DBG_S_C_DMT_PSECT_SIZE): Ditto.
(enum file_type_enum): New type.
(struct location_struct): Removed.
(struct fileinfo, struct srecinfo, struct lineinfo): New types.
(struct funcinfo, struct module): Ditto.
(struct vms_private_data_struct): Update fields.
(struct vms_section_data_struct): New type.
* vms.c: Update copyright year, fix comments,
Fix includes for DECC, add prototypes.
(vms_initialize): Use bfd_alloc instead of bfd_zalloc and remove
some initializers.
Use flavour to set is_vax, location_stack is removed.
(struct pair): Declare.
(fill_section_ptr): Initialize variables at declaration.
Add guard to set SECTION_SYM flag, handlde und section.
(vms_fixup_sections): Use struct pair for fill_section_ptr argument.
(_bfd_vms_slurp_object_records): New function, replaces previous
vms_object_p.
(vms_slurp_module): New function.
(vms_slurp_image): Ditto.
(vms_object_p): Complete rewrite.
(vms_mkobject): Use is_vax field to slect architecture.
(free_reloc_stream): New function.
(vms_convert_to_var): Ditto.
(vms_convert_to_var_1): Ditto.
(vms_convert_to_var_unix_filename): Ditto.
(vms_close_and_cleanup): Call free_reloc_stream, convert file to
VAR format on VMS.
(vms_new_section_hook): Set alignment to 0, allocate private data.
(vms_get_section_contents): Load content.
(vms_get_symbol_info): Handle undefined section.
(vms_find_nearest_line): Handle.
(alloc_reloc_stream): New function.
(vms_slurp_reloc_table): Ditto.
(vms_get_reloc_upper_bound): Make it real.
(vms_canonicalize_reloc): Do the real work.
(alpha_howto_table): Add ALPHA_R_NOP, ALPHA_R_BSR, ALPHA_R_LDA,
ALPHA_R_BOH.
(vms_bfd_reloc_type_lookup): Handle NOP, BSR, LDA and BOH.
(vms_set_arch_mach): Check arch.
(vms_set_section_contents): Copy the content after allocation.
(vms_alpha_vec): Update object flags.
* vms-tir.c: Update copyright year, fix comments,
add prototypes for new functions.
(dst_define_location): New function.
(dst_restore_location): New function.
(dst_retrieve_location): New function.
(dst_check_allocation): New function.
(image_dump): Call dst_check_allocation.
(image_write_b): Ditto.
(image_write_w): Ditto.
(image_write_l): Ditto.
(image_write_q): Ditto.
(cmd_name): Handle STA_LW, STA_QW, STO_OFF, STO_IMM, STO_IMMR, STO_LW,
STO_QW, OPR_ADD, CTL_SETRB, STC_LP_PSB, CTL_DFLOC, CTL_STLOC,
CTL_STKDL.
Call error handler instead of abort if name is not known.
(etir_sta): Add quarter_relocs argument and set it.
Fix cast.
(etir_sto): Ditto.
(etir_opr): Ditto, return FALSE in case of error.
(etir_ctl): Add quarter_relocs argument and set it, fix cast.
Fix CTL_DFLOC, CTL_STLOC, CTL_STKDL.
(etir_stc): Add quarter_relocs argument and set it, fix cast.
Fix STC_LP, STC_LP_PSB, STC_GBL and STC_CGA.
Handle STC_LP_PSB, STC_BSR_GBL, STC_LDA_GBL, STC_BOH_GBL.
Move STC_NOP_PS, STC_BSR_PS, STC_LDA_PS, STC_BOH_PS, STC_NBH_PS.
Return FALSE in case of error.
(tir_sta): Change sign of psect.
(tir_ctl): Ditto.
(tir_cmd): Fix cast. Makes tir_table static const.
(etir_cmd): Add quarter_relocs argument, makes etir_table const,
add argument to explain.
(analyze_etir): Initialize maxptr, add quarter_relocs
declaration, move some declarations into inner scopes.
Handle quarter_relocs and STO_IMM.
(_bfd_vms_slurp_tir): Use constant instead of hard-coded values.
(_bfd_vms_slurp_relocs): New function.
(_bfd_vms_decode_relocs): New function.
(sto_imm): Rewritten.
(start_first_etbt_record): New function.
(start_another_etbt_record): Ditto.
(etir_output_check): Ditto.
(defer_reloc_p): Ditto.
(_bfd_vms_write_tir): Remove nextoffset, convert a while-loop to
a for-loop. Correctly deals with contents, deals with .vmsdebug,
rewritte relocations handling.
(_bfd_vms_write_tbt): Removed.
(_bfd_vms_write_dbg): Ditto.
* vms-misc.c: Update copyright year, Fix comments.
(_bfd_vms_get_header_values): Use 'size' instead of 'length'.
(maybe_adjust_record_pointer_for_object): New function.
(_bfd_vms_get_first_record): New function, replaces ...
(_bfd_vms_get_record): .. removed.
(_bfd_vms_get_object_record): New function.
(_bfd_vms_get_object_record): New function.
(vms_get_remaining_object_record): New function, replaces ...
(_bfd_vms_get_next_record): ... removed.
(add_new_contents): Removed.
(_bfd_save_vms_section): Removed.
(_bfd_get_vms_section): Removed.
(_bfd_vms_output_flush): Write in VAR format.
(new_symbol): Don't make UND section.
* vms-hdr.c: Update copyright year, update list of record handled.
(_bfd_vms_slurp_hdr): rec_length renamed to rec_size.
(_bfd_vms_write_hdr): Strip vms and unix patches,
add comments, truncate module name at 31 characters,
use constants instead of hard-coded value,
write BFD version instead of a fixed string.
(_bfd_vms_slurp_ihd): New function.
(_bfd_vms_slurp_isd): Ditto.
(_bfd_vms_slurp_ihs): Ditto.
(new_module): Ditto.
(parse_module): Ditto
(build_module_list): Ditto.
(module_find_nearest_line): Ditto.
(_bfd_vms_find_nearest_dst_line): Ditto.
(vms_slurp_debug): Ditto.
(_bfd_vms_slurp_dbg): Ditto.
(_bfd_vms_slurp_tbt): Ditto.
(_bfd_vms_write_dbg): Ditto.
(_bfd_vms_write_tbt): Ditto.
* vms-gsd.c: Update copyright year, update list of records handled.
(EVAX_LITERALS_NAME): New macro.
(evax_section_flags): Add an entry for EVAX_LITERALS_NAME.
(gpsflagdesc, gsyflagdesc): Moved out of _bfd_vms_slurp_gsd.
(register_universal_symbol): New function and prototype.
(_bfd_vms_slurp_gsd): Fix indentations and casts,
improve debug messages,
use constants instead of hard-coded value,
fix missing endianness conversion,
handle global symbol (SYMG).
(bfd_vms_set_section_flags): New function.
(_bfd_vms_write_gsd): Don't write .vmsdebug section,
handle section literals,
fix indentation,
handle section bfd and vms flags,
don't output LIB$INITIALIZE symbol,
fix handling of weak symbols,
fix evax vs vax procedure descriptor,
handle absolute symbols.
* reloc.c (BFD_RELOC_ALPHA_NOP, BFD_RELOC_ALPHA_BSR,
BFD_RELOC_ALPHA_LDA, BFD_RELOC_ALPHA_BOH): New relocations.
* makefile.vms (DEFS): Fix flags for VMS.
* bfdio.c (real_fopen): Handle multiple VMS fopen attributes.
* bfd-in2.h: Regenerated.
* libbfd.h: Regenerated.
+2009-02-23 Tristan Gingold <gingold@adacore.com>
+
+ * vms.h: Update copyright year, fix comments, reorder declarations.
+ (_bfd_save_vms_section): Remove the prototype.
+ (EGPS_S_V_NO_SHIFT): New constant.
+ (bfd_vms_set_section_flags): New prototype.
+ (EGPS_S_B_ALIGN, EGPS_S_W_FLAGS, EGPS_S_L_ALLOC, EGPS_S_B_NAMLNG): New
+ constants.
+ (EGSY_S_W_FLAGS): Ditto.
+ (EGSY_S_V_QUAD_VAL): Ditto.
+ (ESDF_S_L_VALUE, ESDF_S_L_PSINDX, ESDF_S_B_NAMLNG): Ditto.
+ (EGST_S_W_FLAGS, EGST_S_Q_LP_1, EGST_S_Q_LP_2, EGST_S_L_PSINDX,
+ EGST_S_B_NAMLNG): Ditto.
+ (ESRF_S_B_NAMLNG): Ditto.
+ (ETIR_S_C_HEADER_SIZE): Ditto.
+ (EGPS_S_V_ALLOC_64BIT): Ditto.
+ (DST_S_C_EPILOG): Ditto.
+ (DST_S_C_SRC_SETLNUM_L, DST_S_C_SRC_SETLNUM_W) : Ditto.
+ (DST_S_C_SRC_INCRLNUM_B): Ditto.
+ (DST_S_B_PCLINE_UNSBYTE, DST_S_W_PCLINE_UNSWORD): Ditto.
+ (DST_S_L_PCLINE_UNSLONG): Ditto.
+ (DST_S_B_MODBEG_NAME, DST_S_L_RTNBEG_ADDRESS) : Ditto
+ (DST_S_B_RTNBEG_NAME, DST_S_L_RTNEND_SIZE): Ditto
+ (DST_S_C_SOURCE_HEADER_SIZE): Ditto.
+ (DST_S_B_SRC_DF_LENGTH, DST_S_W_SRC_DF_FILEID): Ditto.
+ (DST_S_B_SRC_DF_FILENAME, DST_S_B_SRC_UNSBYTE): Ditto.
+ (DST_S_B_SRC_UNSBYTE): Ditto.
+ (DST_S_W_SRC_UNSWORD, DST_S_L_SRC_UNSLONG): Ditto.
+ Add prototypes.
+ (vms_section, vms_reloc): Remove types.
+ (hdr_struc): Replaced by ...
+ (hdr_struct): ... new type.
+ (EMH_S_W_HDRTYP, EMH_S_B_STRLVL, EMH_S_L_ARCH1): New constants.
+ (EMH_S_L_ARCH2, EMH_S_L_RECSIZ, EMH_S_B_NAMLNG): Ditto.
+ (EMH_DATE_LENGTH): Ditto.
+ (eom_struc): Replaced by ...
+ (eom_struct): ... new type.
+ (EEOM_S_L_TOTAL_LPS, EEOM_S_W_COMCOD, EEOM_S_B_TFRFLG): New constants.
+ (EEOM_S_L_PSINDX, EEOM_S_L_TFRADR): Ditto.
+ (EIHD_S_K_MAJORID, EIHD_S_K_MINORID, EIHD_S_K_EXE): Ditto.
+ (EIHD_S_L_SIZE, EIHD_S_L_ISDOFF, EIHD_S_L_SYMDBGOFF): Ditto.
+ (EIHD_S_Q_SYMVVA, EIHD_S_L_IMGTYPE): Ditto.
+ (EISD_S_L_EISDSIZE, EISD_S_L_SECSIZE, EISD_S_Q_VIR_ADDR): Ditto.
+ (EISD_S_L_FLAGS, EISD_S_L_VBN, EISD_S_R_CONTROL): Ditto.
+ (EISD_S_L_IDENT, EISD_S_T_GBLNAM): Ditto.
+ (EISD_S_M_GBL, EISD_S_M_CRF, EISD_S_M_DZRO, EISD_S_M_WRT): Ditto.
+ (EISD_S_M_INITALCODE, EISD_S_M_BASED, EISD_S_M_FIXUPVEC): Ditto.
+ (EISD_S_M_RESIDENT, EISD_S_M_VECTOR, EISD_S_M_PROTECT): Ditto.
+ (EISD_S_M_LASTCLU, EISD_S_M_EXE, EISD_S_M_NONSHRADR): Ditto.
+ (EISD_S_M_QUAD_LENGTH, EISD_S_M_ALLOC_64BIT): Ditto.
+ (EIHS_S_L_DSTVBN, EIHS_S_L_DSTSIZE, EIHS_S_L_GSTVBN): Ditto.
+ (EIHS_S_L_GSTSIZE, EIHS_S_L_DMTVBN, EIHS_S_L_DMTBYTES): Ditto.
+ (DBG_S_L_DMT_MODBEG, DBG_S_L_DST_SIZE): Ditto.
+ (DBG_S_W_DMT_PSECT_COUNT, DBG_S_C_DMT_HEADER_SIZE): Ditto.
+ (DBG_S_L_DMT_PSECT_START, DBG_S_L_DMT_PSECT_LENGTH)
+ (DBG_S_C_DMT_PSECT_SIZE): Ditto.
+ (enum file_type_enum): New type.
+ (struct location_struct): Removed.
+ (struct fileinfo, struct srecinfo, struct lineinfo): New types.
+ (struct funcinfo, struct module): Ditto.
+ (struct vms_private_data_struct): Update fields.
+ (struct vms_section_data_struct): New type.
+
+ * vms.c: Update copyright year, fix comments,
+ Fix includes for DECC, add prototypes.
+ (vms_initialize): Use bfd_alloc instead of bfd_zalloc and remove
+ some initializers.
+ Use flavour to set is_vax, location_stack is removed.
+ (struct pair): Declare.
+ (fill_section_ptr): Initialize variables at declaration.
+ Add guard to set SECTION_SYM flag, handlde und section.
+ (vms_fixup_sections): Use struct pair for fill_section_ptr argument.
+ (_bfd_vms_slurp_object_records): New function, replaces previous
+ vms_object_p.
+ (vms_slurp_module): New function.
+ (vms_slurp_image): Ditto.
+ (vms_object_p): Complete rewrite.
+ (vms_mkobject): Use is_vax field to slect architecture.
+ (free_reloc_stream): New function.
+ (vms_convert_to_var): Ditto.
+ (vms_convert_to_var_1): Ditto.
+ (vms_convert_to_var_unix_filename): Ditto.
+ (vms_close_and_cleanup): Call free_reloc_stream, convert file to
+ VAR format on VMS.
+ (vms_new_section_hook): Set alignment to 0, allocate private data.
+ (vms_get_section_contents): Load content.
+ (vms_get_symbol_info): Handle undefined section.
+ (vms_find_nearest_line): Handle.
+ (alloc_reloc_stream): New function.
+ (vms_slurp_reloc_table): Ditto.
+ (vms_get_reloc_upper_bound): Make it real.
+ (vms_canonicalize_reloc): Do the real work.
+ (alpha_howto_table): Add ALPHA_R_NOP, ALPHA_R_BSR, ALPHA_R_LDA,
+ ALPHA_R_BOH.
+ (vms_bfd_reloc_type_lookup): Handle NOP, BSR, LDA and BOH.
+ (vms_set_arch_mach): Check arch.
+ (vms_set_section_contents): Copy the content after allocation.
+ (vms_alpha_vec): Update object flags.
+
+ * vms-tir.c: Update copyright year, fix comments,
+ add prototypes for new functions.
+ (dst_define_location): New function.
+ (dst_restore_location): New function.
+ (dst_retrieve_location): New function.
+ (dst_check_allocation): New function.
+ (image_dump): Call dst_check_allocation.
+ (image_write_b): Ditto.
+ (image_write_w): Ditto.
+ (image_write_l): Ditto.
+ (image_write_q): Ditto.
+ (cmd_name): Handle STA_LW, STA_QW, STO_OFF, STO_IMM, STO_IMMR, STO_LW,
+ STO_QW, OPR_ADD, CTL_SETRB, STC_LP_PSB, CTL_DFLOC, CTL_STLOC,
+ CTL_STKDL.
+ Call error handler instead of abort if name is not known.
+ (etir_sta): Add quarter_relocs argument and set it.
+ Fix cast.
+ (etir_sto): Ditto.
+ (etir_opr): Ditto, return FALSE in case of error.
+ (etir_ctl): Add quarter_relocs argument and set it, fix cast.
+ Fix CTL_DFLOC, CTL_STLOC, CTL_STKDL.
+ (etir_stc): Add quarter_relocs argument and set it, fix cast.
+ Fix STC_LP, STC_LP_PSB, STC_GBL and STC_CGA.
+ Handle STC_LP_PSB, STC_BSR_GBL, STC_LDA_GBL, STC_BOH_GBL.
+ Move STC_NOP_PS, STC_BSR_PS, STC_LDA_PS, STC_BOH_PS, STC_NBH_PS.
+ Return FALSE in case of error.
+ (tir_sta): Change sign of psect.
+ (tir_ctl): Ditto.
+ (tir_cmd): Fix cast. Makes tir_table static const.
+ (etir_cmd): Add quarter_relocs argument, makes etir_table const,
+ add argument to explain.
+ (analyze_etir): Initialize maxptr, add quarter_relocs
+ declaration, move some declarations into inner scopes.
+ Handle quarter_relocs and STO_IMM.
+ (_bfd_vms_slurp_tir): Use constant instead of hard-coded values.
+ (_bfd_vms_slurp_relocs): New function.
+ (_bfd_vms_decode_relocs): New function.
+ (sto_imm): Rewritten.
+ (start_first_etbt_record): New function.
+ (start_another_etbt_record): Ditto.
+ (etir_output_check): Ditto.
+ (defer_reloc_p): Ditto.
+ (_bfd_vms_write_tir): Remove nextoffset, convert a while-loop to
+ a for-loop. Correctly deals with contents, deals with .vmsdebug,
+ rewritte relocations handling.
+ (_bfd_vms_write_tbt): Removed.
+ (_bfd_vms_write_dbg): Ditto.
+
+ * vms-misc.c: Update copyright year, Fix comments.
+ (_bfd_vms_get_header_values): Use 'size' instead of 'length'.
+ (maybe_adjust_record_pointer_for_object): New function.
+ (_bfd_vms_get_first_record): New function, replaces ...
+ (_bfd_vms_get_record): .. removed.
+ (_bfd_vms_get_object_record): New function.
+ (_bfd_vms_get_object_record): New function.
+ (vms_get_remaining_object_record): New function, replaces ...
+ (_bfd_vms_get_next_record): ... removed.
+ (add_new_contents): Removed.
+ (_bfd_save_vms_section): Removed.
+ (_bfd_get_vms_section): Removed.
+ (_bfd_vms_output_flush): Write in VAR format.
+ (new_symbol): Don't make UND section.
+
+ * vms-hdr.c: Update copyright year, update list of record handled.
+ (_bfd_vms_slurp_hdr): rec_length renamed to rec_size.
+ (_bfd_vms_write_hdr): Strip vms and unix patches,
+ add comments, truncate module name at 31 characters,
+ use constants instead of hard-coded value,
+ write BFD version instead of a fixed string.
+ (_bfd_vms_slurp_ihd): New function.
+ (_bfd_vms_slurp_isd): Ditto.
+ (_bfd_vms_slurp_ihs): Ditto.
+ (new_module): Ditto.
+ (parse_module): Ditto
+ (build_module_list): Ditto.
+ (module_find_nearest_line): Ditto.
+ (_bfd_vms_find_nearest_dst_line): Ditto.
+ (vms_slurp_debug): Ditto.
+ (_bfd_vms_slurp_dbg): Ditto.
+ (_bfd_vms_slurp_tbt): Ditto.
+ (_bfd_vms_write_dbg): Ditto.
+ (_bfd_vms_write_tbt): Ditto.
+
+ * vms-gsd.c: Update copyright year, update list of records handled.
+ (EVAX_LITERALS_NAME): New macro.
+ (evax_section_flags): Add an entry for EVAX_LITERALS_NAME.
+ (gpsflagdesc, gsyflagdesc): Moved out of _bfd_vms_slurp_gsd.
+ (register_universal_symbol): New function and prototype.
+ (_bfd_vms_slurp_gsd): Fix indentations and casts,
+ improve debug messages,
+ use constants instead of hard-coded value,
+ fix missing endianness conversion,
+ handle global symbol (SYMG).
+ (bfd_vms_set_section_flags): New function.
+ (_bfd_vms_write_gsd): Don't write .vmsdebug section,
+ handle section literals,
+ fix indentation,
+ handle section bfd and vms flags,
+ don't output LIB$INITIALIZE symbol,
+ fix handling of weak symbols,
+ fix evax vs vax procedure descriptor,
+ handle absolute symbols.
+
+ * reloc.c (BFD_RELOC_ALPHA_NOP, BFD_RELOC_ALPHA_BSR,
+ BFD_RELOC_ALPHA_LDA, BFD_RELOC_ALPHA_BOH): New relocations.
+
+ * makefile.vms (DEFS): Fix flags for VMS.
+
+ * bfdio.c (real_fopen): Handle multiple VMS fopen attributes.
+
+ * bfd-in2.h: Regenerated.
+ * libbfd.h: Regenerated.
+
2009-02-20 Cary Coutant <ccoutant@google.com>
* vmsutil.c (vms_file_stats_name): Fix incorrect use of st_mtime
STO_ALPHA_STD_GPLOAD. */
BFD_RELOC_ALPHA_BRSGP,
+/* The NOP relocation outputs a NOP if the longword displacement
+between two procedure entry points is < 2^21. */
+ BFD_RELOC_ALPHA_NOP,
+
+/* The BSR relocation outputs a BSR if the longword displacement
+between two procedure entry points is < 2^21. */
+ BFD_RELOC_ALPHA_BSR,
+
+/* The LDA relocation outputs a LDA if the longword displacement
+between two procedure entry points is < 2^16. */
+ BFD_RELOC_ALPHA_LDA,
+
+/* The BOH relocation outputs a BSR if the longword displacement
+between two procedure entry points is < 2^21, or else a hint. */
+ BFD_RELOC_ALPHA_BOH,
+
/* Alpha thread-local storage relocations. */
BFD_RELOC_ALPHA_TLSGD,
BFD_RELOC_ALPHA_TLSLDM,
}
else
{
- /* Attribute found - rebuild modes. */
- size_t modes_len = vms_attr - modes;
-
- BFD_ASSERT (modes_len < sizeof (vms_modes));
- memcpy (vms_modes, modes, modes_len);
- vms_modes[modes_len] = 0;
- return close_on_exec (fopen (filename, vms_modes, vms_attr + 1));
+ /* Attributes found. Split. */
+ size_t modes_len = strlen (modes) + 1;
+ char attrs[modes_len + 1];
+ char *at[3];
+ int i;
+
+ memcpy (attrs, modes, modes_len);
+ at[0] = attrs;
+ for (i = 0; i < 2; i++)
+ {
+ at[i + 1] = strchr (at[i], ',');
+ BFD_ASSERT (at[i + 1] != NULL);
+ *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it. */
+ }
+ return close_on_exec (fopen (filename, at[0], at[1], at[2]));
}
#else /* !VMS */
#if defined (HAVE_FOPEN64)
"BFD_RELOC_ALPHA_GPREL_HI16",
"BFD_RELOC_ALPHA_GPREL_LO16",
"BFD_RELOC_ALPHA_BRSGP",
+ "BFD_RELOC_ALPHA_NOP",
+ "BFD_RELOC_ALPHA_BSR",
+ "BFD_RELOC_ALPHA_LDA",
+ "BFD_RELOC_ALPHA_BOH",
"BFD_RELOC_ALPHA_TLSGD",
"BFD_RELOC_ALPHA_TLSLDM",
"BFD_RELOC_ALPHA_DTPMOD64",
CFLAGS=/include=([],[-.include])$(DEFS)
else
ifeq ($(ARCH),ALPHA)
-DEFS=/define=(SELECT_VECS="&vms_alpha_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch",\
-"HAVE_vms_alpha_vec=1","unlink=remove","DEBUGDIR=NULL")
+DEFS=/define=(SELECT_VECS="&vms_alpha_vec",\
+ SELECT_ARCHITECTURES="&bfd_alpha_arch",\
+ "HAVE_vms_alpha_vec=1","unlink=remove","DEBUGDIR=NULL")
else
DEFS=/define=(SELECT_VECS="&vms_vax_vec",SELECT_ARCHITECTURES="&bfd_vax_arch",\
-"HAVE_vms_vax_vec=1","unlink=remove","const=")
+ "HAVE_vms_vax_vec=1","unlink=remove")
endif
-CFLAGS=/noopt/debug/show=incl/name=(as_is,shortened)/include=([],[-.include])$(DEFS)/warnings=disable=(missingreturn,longextern)
+OPT=/noopt/debug
+CFLAGS=/name=(as_is,shortened)/include=([],[-.include])$(DEFS)$(OPT)
endif
share a common GP, and the target address is adjusted for
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
/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007 Free Software Foundation, Inc.
+ 2007, 2009 Free Software Foundation, Inc.
- go and read the openVMS linker manual (esp. appendix B)
+ GSD record handling functions
+ EGSD record handling functions
+
+ Go and read the openVMS linker manual (esp. appendix B)
if you don't know what's going on here :-)
Written by Klaus K"ampf (kkaempf@rmi.de)
#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$"
(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),
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 *
/* Input routines. */
+static int register_universal_symbol (bfd *abfd, asymbol *symbol,
+ int vms_flags);
+
/* Process GSD/EGSD record
return 0 on success, -1 on error. */
int
_bfd_vms_slurp_gsd (bfd * abfd, int objtype)
{
-#if VMS_DEBUG
- static struct flagdescstruct gpsflagdesc[] =
- {
- { "PIC", 0x0001 },
- { "LIB", 0x0002 },
- { "OVR", 0x0004 },
- { "REL", 0x0008 },
- { "GBL", 0x0010 },
- { "SHR", 0x0020 },
- { "EXE", 0x0040 },
- { "RD", 0x0080 },
- { "WRT", 0x0100 },
- { "VEC", 0x0200 },
- { "NOMOD", 0x0400 },
- { "COM", 0x0800 },
- { NULL, 0 }
- };
-
- static struct flagdescstruct gsyflagdesc[] =
- {
- { "WEAK", 0x0001 },
- { "DEF", 0x0002 },
- { "UNI", 0x0004 },
- { "REL", 0x0008 },
- { "COMM", 0x0010 },
- { "VECEP", 0x0020 },
- { "NORM", 0x0040 },
- { NULL, 0 }
- };
-#endif
-
int gsd_type, gsd_size;
asection *section;
unsigned char *vms_rec;
vms_rec = PRIV (vms_rec);
if (objtype == OBJ_S_C_GSD)
- gsd_type = *vms_rec;
+ gsd_type = vms_rec[0];
else
{
_bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
vms_debug (4, "GSD_S_C_PSC\n");
#endif
/* If this section isn't a bfd section. */
- if (PRIV (is_vax) && (psect_idx < (abfd->section_count-1)))
+ if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1)))
{
/* Check for temporary section from TIR record. */
if (psect_idx < PRIV (section_count))
base_addr += section->size;
/* Global section is common symbol. */
-
if (old_flags & GPS_S_M_GBL)
{
entry = _bfd_vms_enter_symbol (abfd, name);
else
psect = vms_rec[value_offset-1];
- symbol->section = (asection *) (size_t) psect;
+ symbol->section = (asection *)(unsigned long)psect;
#if VMS_DEBUG
- vms_debug (4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount,
- symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
+ vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount,
+ symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags));
#endif
}
else
{
/* Symbol reference. */
- symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
#if VMS_DEBUG
- vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n",
- abfd->symcount, symbol->name, symbol->section->name,
- symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
+ vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
+ symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
#endif
+ symbol->section = (asection *)(unsigned long)-1;
}
gsd_size = vms_rec[name_offset] + name_offset + 1;
case EGSD_S_C_PSC + EVAX_OFFSET:
{
/* Program section definition. */
- name = _bfd_vms_save_counted_string (vms_rec + 12);
+ name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG);
section = bfd_make_section (abfd, name);
if (!section)
return -1;
- old_flags = bfd_getl16 (vms_rec + 6);
- section->size = bfd_getl32 (vms_rec + 8); /* Allocation. */
+ old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS);
+ section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC);
new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
section->size > 0);
if (old_flags & EGPS_S_V_REL)
new_flags |= SEC_RELOC;
if (!bfd_set_section_flags (abfd, section, new_flags))
return -1;
- section->alignment_power = vms_rec[4];
+ section->alignment_power = vms_rec[EGPS_S_B_ALIGN];
align_addr = (1 << section->alignment_power);
if ((base_addr % align_addr) != 0)
base_addr += (align_addr - (base_addr % align_addr));
section->contents = bfd_zmalloc (section->size);
if (section->contents == NULL)
return -1;
+ section->filepos = (unsigned int)-1;
#if VMS_DEBUG
- vms_debug (4, "egsd psc %d (%s, flags %04x=%s) ",
- section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
+ vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ",
+ section->index, name, old_flags, flag2str(gpsflagdesc, old_flags));
vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
section->size, section->vma, section->contents);
#endif
case EGSD_S_C_SYM + EVAX_OFFSET:
{
- /* Symbol specification (definition or reference). */
+ /* Global symbol specification (definition or reference). */
symbol = bfd_make_empty_symbol (abfd);
if (symbol == 0)
return -1;
- old_flags = bfd_getl16 (vms_rec + 6);
+ old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS);
new_flags = BSF_NO_FLAGS;
if (old_flags & EGSY_S_V_WEAK)
new_flags |= BSF_WEAK;
- if (vms_rec[6] & EGSY_S_V_DEF)
+ if (old_flags & EGSY_S_V_DEF)
{
/* Symbol definition. */
- symbol->name = _bfd_vms_save_counted_string (vms_rec + 32);
if (old_flags & EGSY_S_V_NORM)
- /* Proc def. */
new_flags |= BSF_FUNCTION;
-
- symbol->value = bfd_getl64 (vms_rec + 8);
- symbol->section = (asection *) ((unsigned long) bfd_getl32 (vms_rec + 28));
+ symbol->name =
+ _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG);
+ symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE);
+ symbol->section =
+ (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX);
#if VMS_DEBUG
- vms_debug (4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount,
- symbol->name, (int) symbol->section, old_flags,
- flag2str (gsyflagdesc, old_flags));
+ vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n",
+ abfd->symcount, symbol->name, (long)symbol->section,
+ old_flags, flag2str (gsyflagdesc, old_flags));
#endif
}
else
{
/* Symbol reference. */
- symbol->name = _bfd_vms_save_counted_string (vms_rec + 8);
+ symbol->name =
+ _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG);
#if VMS_DEBUG
- vms_debug (4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
- symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
+ vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n",
+ abfd->symcount, symbol->name, old_flags,
+ flag2str (gsyflagdesc, old_flags));
#endif
- symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
+ symbol->section = (asection *)(unsigned long)-1;
}
symbol->flags = new_flags;
- /* Save symbol in vms_symbol_table. */
- entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
- symbol->name,
- TRUE, FALSE);
+ /* Register symbol in VMS symbol table. */
+ entry = (vms_symbol_entry *) bfd_hash_lookup
+ (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE);
+
if (entry == NULL)
{
bfd_set_error (bfd_error_no_memory);
}
break;
- case EGSD_S_C_IDC + EVAX_OFFSET:
+ case EGSD_S_C_SYMG + EVAX_OFFSET:
+ {
+ /* Universal symbol specification (definition). */
+ symbol = bfd_make_empty_symbol (abfd);
+ if (symbol == 0)
+ return -1;
+
+ old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS);
+ new_flags = BSF_NO_FLAGS;
+
+ if (old_flags & EGSY_S_V_WEAK)
+ new_flags |= BSF_WEAK;
+
+ if (old_flags & EGSY_S_V_DEF) /* symbol definition */
+ {
+ if (old_flags & EGSY_S_V_NORM)
+ new_flags |= BSF_FUNCTION;
+
+ symbol->name =
+ _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG);
+
+ /* For BSF_FUNCTION symbols, the entry point is in LP_1
+ and the descriptor in LP_2. For other symbols, the
+ unique value is in LP_2. */
+ symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2);
+
+ /* Adding this offset is necessary in order for GDB to
+ read the DWARF-2 debug info from shared libraries. */
+ if (abfd->flags & DYNAMIC
+ && strstr (symbol->name, "$DWARF2.DEBUG") != 0)
+ symbol->value += PRIV (symvva);
+ }
+ else /* symbol reference */
+ (*_bfd_error_handler) ("Invalid EGST reference");
+
+ symbol->flags = new_flags;
+
+ if (register_universal_symbol (abfd, symbol, old_flags) < 0)
+ return -1;
+
+ /* Make a second symbol for the entry point. */
+ if (symbol->flags & BSF_FUNCTION)
+ {
+ asymbol *en_sym;
+ char *name = bfd_alloc (abfd, strlen (symbol->name) + 5);
+
+ en_sym = bfd_make_empty_symbol (abfd);
+ if (en_sym == 0)
+ return -1;
+
+ strcpy (name, symbol->name);
+ strcat (name, "..en");
+
+ en_sym->name = name;
+ en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);
+
+ if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
+ return -1;
+ }
+ }
break;
+ case EGSD_S_C_IDC + EVAX_OFFSET:
+ break;
+
default:
- (*_bfd_error_handler) (_("unknown gsd/egsd subtype %d"), gsd_type);
+ (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
bfd_set_error (bfd_error_bad_value);
return -1;
}
return 0;
}
-/* Output routines. */
+/* Register a universal symbol in the VMS symbol table. */
+
+static int
+register_universal_symbol (bfd *abfd, asymbol *symbol, int vms_flags)
+{
+ bfd_vma sbase = 0;
+ asection *s, *sec = NULL;
+ vms_symbol_entry *entry;
+
+ /* A universal symbol is by definition global... */
+ symbol->flags |= BSF_GLOBAL;
+
+ /* ...and dynamic in shared libraries. */
+ if (abfd->flags & DYNAMIC)
+ symbol->flags |= BSF_DYNAMIC;
+
+ /* Find containing section. */
+ for (s = abfd->sections; s; s = s->next)
+ {
+ if (symbol->value >= s->vma
+ && s->vma > sbase
+ && !(s->flags & SEC_COFF_SHARED_LIBRARY)
+ && (s->size > 0 || !(vms_flags & EGSY_S_V_REL)))
+ {
+ sbase = s->vma;
+ sec = s;
+ }
+ }
+
+ symbol->value -= sbase;
+ symbol->section = sec;
+
+#if VMS_DEBUG
+ vms_debug (4, "EGST sym def #%d (%s, 0x%llx => 0x%llx, %04x=%s)\n",
+ abfd->symcount, symbol->name, symbol->value + sbase,
+ symbol->value, vms_flags,
+ flag2str(gsyflagdesc, vms_flags));
+#endif
+
+ entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
+ symbol->name,
+ TRUE, FALSE);
+
+ if (entry == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return -1;
+ }
+
+ if (entry->symbol) /* FIXME: DEC C generates this */
+ {
+#if VMS_DEBUG
+ vms_debug (4, "EGSD_S_C_SYMG: duplicate \"%s\"\n", symbol->name);
+#endif
+ }
+ else
+ {
+ entry->symbol = symbol;
+ PRIV (gsd_sym_count)++;
+ abfd->symcount++;
+ }
+
+ return 0;
+}
+
+/* Set section VMS flags. */
+
+void
+bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec, flagword flags)
+{
+ vms_section_data (sec)->vflags = flags;
+}
/* Write section and symbol directory of bfd abfd. */
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);
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)
{
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))
_bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
_bfd_vms_output_short (abfd, section->alignment_power & 0xff);
+
if (bfd_is_com_section (section))
- new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
+ new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD
+ | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
else
new_flags = vms_esecflag_by_name (evax_section_flags, sname,
section->size > 0);
+ /* Modify them as directed. */
+ if (section->flags & SEC_READONLY)
+ new_flags &= ~EGPS_S_V_WRT;
+
+ new_flags |= vms_section_data (section)->vflags & 0xffff;
+ new_flags &=
+ ~((vms_section_data (section)->vflags >> EGPS_S_V_NO_SHIFT) & 0xffff);
+
+#if VMS_DEBUG
+ vms_debug (3, "sec flags %x\n", section->flags);
+ vms_debug (3, "new_flags %x, _raw_size %d\n", new_flags, section->size);
+#endif
+
_bfd_vms_output_short (abfd, new_flags);
_bfd_vms_output_long (abfd, (unsigned long) section->size);
_bfd_vms_output_counted (abfd, sname);
_bfd_vms_output_flush (abfd);
last_index = section->index;
+done:
section = section->next;
}
if (old_flags & BSF_FILE)
continue;
- if (((old_flags & (BSF_GLOBAL | BSF_WEAK)) == 0) /* Not xdef... */
- && (!bfd_is_und_section (symbol->section))) /* ...and not xref. */
- continue; /* Dont output. */
+ if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */
+ && !bfd_is_und_section (symbol->section) /* and not xref... */
+ && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */
+ && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
+ continue;
/* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */
if (_bfd_vms_output_check (abfd, 80) < 0)
if (old_flags & BSF_WEAK)
new_flags |= EGSY_S_V_WEAK;
- if (bfd_is_com_section (symbol->section))
+ if (bfd_is_com_section (symbol->section)) /* .comm */
new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
if (old_flags & BSF_FUNCTION)
new_flags |= EGSY_S_V_NORM;
new_flags |= EGSY_S_V_REL;
}
- if (old_flags & (BSF_GLOBAL | BSF_WEAK))
+ if (old_flags & BSF_GLOBAL)
{
new_flags |= EGSY_S_V_DEF;
if (!bfd_is_abs_section (symbol->section))
}
_bfd_vms_output_short (abfd, new_flags);
- if (old_flags & (BSF_GLOBAL | BSF_WEAK))
+ if (old_flags & BSF_GLOBAL)
{
/* Symbol definition. */
uquad code_address = 0;
if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
{
- code_address = ((asymbol *) (symbol->udata.p))->value;
- ca_psindx = ((asymbol *) (symbol->udata.p))->section->index;
+ asymbol *sym;
+
+ if (bfd_get_flavour (abfd) == bfd_target_evax_flavour)
+ sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
+ else
+ sym = (asymbol *)symbol->udata.p;
+ code_address = sym->value;
+ ca_psindx = sym->section->index;
}
- psindx = symbol->section->index;
+ if (bfd_is_abs_section (symbol->section))
+ psindx = abs_section_index;
+ else
+ psindx = symbol->section->index;
_bfd_vms_output_quad (abfd, symbol->value);
_bfd_vms_output_quad (abfd, code_address);
/* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
- 2007 Free Software Foundation, Inc.
+ 2007, 2008, 2009 Free Software Foundation, Inc.
HDR record handling functions
EMH record handling functions
- and
+
EOM record handling functions
EEOM record handling functions
+ IHD record handling functions
+ EIHD record handling functions
+
+ ISD record handling functions
+ EISD record handling functions
+
+ IHS record handling functions
+ EIHS record handling functions
+
+ DBG record handling functions
+ EDBG record handling functions
+
+ TBT record handling functions
+ ETBT record handling functions
+
+ DST/DMT section handling functions
+
Written by Klaus K"ampf (kkaempf@rmi.de)
This program is free software; you can redistribute it and/or modify
#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. */
break;
case MHD_S_C_LNM:
- PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
+ PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
break;
case MHD_S_C_SRC:
- PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
+ PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
break;
case MHD_S_C_TTL:
- PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
+ PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
break;
case EMH_S_C_MHD + EVAX_OFFSET:
break;
case EMH_S_C_LNM + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
+ PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
break;
case EMH_S_C_SRC + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
+ PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
break;
case EMH_S_C_TTL + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
+ PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
break;
case MHD_S_C_CPR:
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);
fptr = bfd_get_filename (abfd);
fname = strdup (fptr);
+
+ /* Strip VMS path. */
fout = strrchr (fname, ']');
- if (fout == 0)
+ if (fout == NULL)
fout = strchr (fname, ':');
- if (fout != 0)
+ if (fout != NULL)
fout++;
else
fout = fname;
+ /* Strip UNIX path. */
+ fptr = strrchr (fout, '/');
+ if (fptr != NULL)
+ fout = fptr + 1;
+
/* Strip .obj suffix. */
- fptr = strrchr (fname, '.');
- if ((fptr != 0)
- && (strcasecmp (fptr, ".OBJ") == 0))
+ fptr = strrchr (fout, '.');
+ if (fptr != 0 && strcasecmp (fptr, ".OBJ") == 0)
*fptr = 0;
+ /* Convert to upper case and truncate at 31 characters.
+ (VMS object file format restricts module name length to 31). */
fptr = fout;
while (*fptr != 0)
{
*fptr = TOUPPER (*fptr);
fptr++;
- if ((*fptr == ';')
- || ((fptr - fout) > 31))
+ if (*fptr == ';' || (fptr - fout) >= 31)
*fptr = 0;
}
_bfd_vms_output_counted (abfd, fout);
_bfd_vms_output_counted (abfd, "NONAME");
_bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
- _bfd_vms_output_dump (abfd, get_vms_time_string (), 17);
- _bfd_vms_output_fill (abfd, 0, 17);
+ _bfd_vms_output_dump (abfd, get_vms_time_string (), EMH_DATE_LENGTH);
+ _bfd_vms_output_fill (abfd, 0, EMH_DATE_LENGTH);
_bfd_vms_output_flush (abfd);
/* LMN. */
_bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM);
- _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("GAS proGIS"));
+ snprintf (version, sizeof (version), "GAS BFD v%s", BFD_VERSION_STRING);
+ _bfd_vms_output_dump (abfd, (unsigned char *)version, strlen (version));
_bfd_vms_output_flush (abfd);
/* SRC. */
}
else
{
- PRIV (eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4);
- PRIV (eom_data).eom_b_comcod = *(vms_rec + 8);
-
- if (PRIV (eom_data).eom_b_comcod > 1)
+ PRIV (eom_data).eom_l_total_lps
+ = bfd_getl32 (vms_rec + EEOM_S_L_TOTAL_LPS);
+ PRIV (eom_data).eom_w_comcod = bfd_getl16 (vms_rec + EEOM_S_W_COMCOD);
+ if (PRIV (eom_data).eom_w_comcod > 1)
{
(*_bfd_error_handler) (_("Object module NOT error-free !\n"));
bfd_set_error (bfd_error_bad_value);
if (PRIV (rec_size) > 10)
{
PRIV (eom_data).eom_has_transfer = TRUE;
- PRIV (eom_data).eom_b_tfrflg = *(vms_rec + 9);
- PRIV (eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12);
- PRIV (eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16);
+ PRIV (eom_data).eom_b_tfrflg = vms_rec[EEOM_S_B_TFRFLG];
+ PRIV (eom_data).eom_l_psindx
+ = bfd_getl32 (vms_rec + EEOM_S_L_PSINDX);
+ PRIV (eom_data).eom_l_tfradr
+ = bfd_getl32 (vms_rec + EEOM_S_L_TFRADR);
abfd->start_address = PRIV (eom_data).eom_l_tfradr;
}
_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;
+}
-/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
+/* vms-misc.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007, 2008 Free Software Foundation, Inc.
+ 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ Miscellaneous functions.
Written by Klaus K"ampf (kkaempf@rmi.de)
#include "libbfd.h"
#include "vms.h"
-\f
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+static int hash_string PARAMS ((const char *));
+static asymbol *new_symbol PARAMS ((bfd *, char *));
+static void maybe_adjust_record_pointer_for_object PARAMS ((bfd *));
+static int vms_get_remaining_object_record PARAMS ((bfd *, int ));
+static int vms_get_remaining_image_record PARAMS ((bfd *, int ));
+
#if VMS_DEBUG
/* Debug functions. */
-/* Debug function for all vms extensions
- evaluates environment variable VMS_DEBUG for a
- numerical value on the first call
- all error levels below this value are printed
+/* Debug function for all vms extensions evaluates environment
+ variable VMS_DEBUG for a numerical value on the first call all
+ error levels below this value are printed:
- levels:
+ Levels:
1 toplevel bfd calls (functions from the bfd vector)
2 functions called by bfd calls
...
9 almost everything
- level is also indentation level. Indentation is performed
+ Level is also indentation level. Indentation is performed
if level > 0. */
void
\f
/* Object file input functions. */
-/* Return type and length from record header (buf) on Alpha. */
+/* Return type and size from record header (buf) on Alpha. */
void
_bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
unsigned char *buf,
int *type,
- int *length)
+ int *size)
{
- if (type != 0)
+ if (type)
*type = bfd_getl16 (buf);
- buf += 2;
- if (length != 0)
- *length = bfd_getl16 (buf);
+
+ if (size)
+ *size = bfd_getl16 (buf+2);
#if VMS_DEBUG
- vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
+ vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
+ type ? *type : 0, size ? *size : 0);
#endif
}
The openVMS object file has 'variable length' which means that
read() returns data in chunks of (hopefully) correct and expected
- size. The linker (and other tools on vms) depend on that. Unix doesn't
- know about 'formatted' files, so reading and writing such an object
- file in a unix environment is not trivial.
+ size. The linker (and other tools on VMS) depend on that. Unix
+ doesn't know about 'formatted' files, so reading and writing such
+ an object file in a Unix environment is not trivial.
- With the tool 'file' (available on all vms ftp sites), one
- can view and change the attributes of a file. Changing from
+ With the tool 'file' (available on all VMS FTP sites), one
+ can view and change the attributes of a file. Changing from
'variable length' to 'fixed length, 512 bytes' reveals the
- record length at the first 2 bytes of every record. The same
- happens during the transfer of object files from vms to unix,
- at least with ucx, dec's implementation of tcp/ip.
+ record size at the first 2 bytes of every record. The same
+ happens during the transfer of object files from VMS to Unix,
+ at least with UCX, the DEC implementation of TCP/IP.
- The vms format repeats the length at bytes 2 & 3 of every record.
+ The VMS format repeats the size at bytes 2 & 3 of every record.
On the first call (file_format == FF_UNKNOWN) we check if
the first and the third byte pair (!) of the record match.
- If they do it's an object file in an unix environment or with
- wrong attributes (FF_FOREIGN), else we should be in a vms
+ If they do it's an object file in an Unix environment or with
+ wrong attributes (FF_FOREIGN), else we should be in a VMS
environment where read() returns the record size (FF_NATIVE).
- Reading is always done in 2 steps.
- First just the record header is read and the length extracted
- by get_header_values,
- then the read buffer is adjusted and the remaining bytes are
- read in.
+ Reading is always done in 2 steps:
+ 1. first just the record header is read and the size extracted,
+ 2. then the read buffer is adjusted and the remaining bytes are
+ read in.
+
+ All file I/O is done on even file positions. */
- All file i/o is always done on even file positions. */
+#define VMS_OBJECT_ADJUSTMENT 2
+
+static void
+maybe_adjust_record_pointer_for_object (bfd *abfd)
+{
+ /* Set the file format once for all on the first invocation. */
+ if (PRIV (file_format) == FF_UNKNOWN)
+ {
+ if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4]
+ && PRIV (vms_rec)[1] == PRIV (vms_rec)[5])
+ PRIV (file_format) = FF_FOREIGN;
+ else
+ PRIV (file_format) = FF_NATIVE;
+ }
+
+ /* The adjustment is needed only in an Unix environment. */
+ if (PRIV (file_format) == FF_FOREIGN)
+ PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT;
+}
+
+/* Get first record from file and return the file type. */
int
-_bfd_vms_get_record (bfd * abfd)
+_bfd_vms_get_first_record (bfd *abfd)
{
- int test_len, test_start, remaining;
- unsigned char *vms_buf;
+ unsigned int test_len;
#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_get_record\n");
+ vms_debug (8, "_bfd_vms_get_first_record\n");
#endif
- /* Minimum is 6 bytes on Alpha
- (2 bytes length, 2 bytes record id, 2 bytes length repeated)
-
- On the VAX there's no length information in the record
- so start with OBJ_S_C_MAXRECSIZ. */
+ if (PRIV (is_vax))
+ test_len = 0;
+ else
+ /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
+ 2 bytes size repeated) and 12 bytes for images (4 bytes major id,
+ 4 bytes minor id, 4 bytes length). */
+ test_len = 12;
+ /* Size the main buffer. */
if (PRIV (buf_size) == 0)
{
- bfd_size_type amt;
-
- if (PRIV (is_vax))
- {
- amt = OBJ_S_C_MAXRECSIZ;
- PRIV (file_format) = FF_VAX;
- }
- else
- amt = 6;
- PRIV (vms_buf) = bfd_malloc (amt);
+ /* On VAX there's no size information in the record, so
+ start with OBJ_S_C_MAXRECSIZ. */
+ bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ);
+ PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
PRIV (buf_size) = amt;
}
- vms_buf = PRIV (vms_buf);
+ /* Initialize the record pointer. */
+ PRIV (vms_rec) = PRIV (vms_buf);
- if (vms_buf == 0)
- return -1;
-
- switch (PRIV (file_format))
+ /* We only support modules on VAX. */
+ if (PRIV (is_vax))
{
- case FF_UNKNOWN:
- case FF_FOREIGN:
- test_len = 6; /* Probe 6 bytes. */
- test_start = 2; /* Where the record starts. */
- break;
-
- case FF_NATIVE:
- test_len = 4;
- test_start = 0;
- break;
-
- default:
- case FF_VAX:
- test_len = 0;
- test_start = 0;
- break;
+ if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+ return FT_UNKNOWN;
+
+#if VMS_DEBUG
+ vms_debug (2, "file type is VAX module\n");
+#endif
+
+ return FT_MODULE;
}
- /* Skip odd alignment byte. */
+ if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return FT_UNKNOWN;
+ }
- if (bfd_tell (abfd) & 1)
+ /* Is it an image? */
+ if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID)
+ && (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID))
{
- if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
+ if (vms_get_remaining_image_record (abfd, test_len) <= 0)
+ return FT_UNKNOWN;
+
+#if VMS_DEBUG
+ vms_debug (2, "file type is image\n");
+#endif
+
+ return FT_IMAGE;
}
- /* Read the record header on Alpha. */
- if ((test_len != 0)
- && (bfd_bread (PRIV (vms_buf), (bfd_size_type) test_len, abfd)
- != (bfd_size_type) test_len))
+ /* Assume it's a module and adjust record pointer if necessary. */
+ maybe_adjust_record_pointer_for_object (abfd);
+
+ /* But is it really a module? */
+ if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP
+ && bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ)
{
- bfd_set_error (bfd_error_file_truncated);
- return 0;
+ if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+ return FT_UNKNOWN;
+
+#if VMS_DEBUG
+ vms_debug (2, "file type is module\n");
+#endif
+
+ return FT_MODULE;
}
- /* Check file format on first call. */
- if (PRIV (file_format) == FF_UNKNOWN)
- { /* Record length repeats ? */
- if (vms_buf[0] == vms_buf[4]
- && vms_buf[1] == vms_buf[5])
+#if VMS_DEBUG
+ vms_debug (2, "file type is unknown\n");
+#endif
+
+ return FT_UNKNOWN;
+}
+
+/* Implement step #1 of the object record reading procedure.
+ Return the record type or -1 on failure. */
+
+int
+_bfd_vms_get_object_record (bfd *abfd)
+{
+ unsigned int test_len;
+ int type;
+
+#if VMS_DEBUG
+ vms_debug (8, "_bfd_vms_get_obj_record\n");
+#endif
+
+ if (PRIV (is_vax))
+ test_len = 0;
+ else
+ {
+ /* See _bfd_vms_get_first_record. */
+ test_len = 6;
+
+ /* Skip odd alignment byte. */
+ if (bfd_tell (abfd) & 1)
{
- PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment. */
- test_start = 2;
+ if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
}
- else
+
+ /* Read the record header */
+ if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
{
- PRIV (file_format) = FF_NATIVE; /* N: native environment. */
- test_start = 0;
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
}
+
+ /* Reset the record pointer. */
+ PRIV (vms_rec) = PRIV (vms_buf);
+ maybe_adjust_record_pointer_for_object (abfd);
}
+ if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+ return -1;
+
+ if (PRIV (is_vax))
+ type = PRIV (vms_rec) [0];
+ else
+ type = bfd_getl16 (PRIV (vms_rec));
+
+#if VMS_DEBUG
+ vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
+ PRIV (vms_rec), PRIV (rec_size), type);
+#endif
+
+ return type;
+}
+
+/* Implement step #2 of the object record reading procedure.
+ Return the size of the record or 0 on failure. */
+
+static int
+vms_get_remaining_object_record (bfd *abfd, int read_so_far)
+{
+#if VMS_DEBUG
+ vms_debug (8, "vms_get_remaining_obj_record\n");
+#endif
+
if (PRIV (is_vax))
{
- PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size),
- abfd);
- if (PRIV (rec_length) <= 0)
+ if (read_so_far != 0)
+ abort ();
+
+ PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd);
+
+ if (PRIV (rec_size) <= 0)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
- PRIV (vms_rec) = vms_buf;
+
+ /* Reset the record pointer. */
+ PRIV (vms_rec) = PRIV (vms_buf);
}
else
{
- /* Alpha. */
- /* Extract vms record length. */
+ unsigned int to_read;
- _bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL,
- & PRIV (rec_length));
+ /* Extract record size. */
+ PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
- if (PRIV (rec_length) <= 0)
+ if (PRIV (rec_size) <= 0)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
/* That's what the linker manual says. */
-
- if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
+ if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
- /* Adjust the buffer. */
+ /* Take into account object adjustment. */
+ to_read = PRIV (rec_size);
+ if (PRIV (file_format) == FF_FOREIGN)
+ to_read += VMS_OBJECT_ADJUSTMENT;
- if (PRIV (rec_length) > PRIV (buf_size))
+ /* Adjust the buffer. */
+ if (to_read > PRIV (buf_size))
{
- PRIV (vms_buf) = bfd_realloc_or_free (vms_buf,
- (bfd_size_type) PRIV (rec_length));
- vms_buf = PRIV (vms_buf);
- if (vms_buf == 0)
- return -1;
- PRIV (buf_size) = PRIV (rec_length);
+ PRIV (vms_buf)
+ = (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read);
+ if (PRIV (vms_buf) == NULL)
+ return 0;
+ PRIV (buf_size) = to_read;
}
/* Read the remaining record. */
- remaining = PRIV (rec_length) - test_len + test_start;
+ to_read -= read_so_far;
#if VMS_DEBUG
- vms_debug (10, "bfd_bread remaining %d\n", remaining);
+ vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
#endif
- if (bfd_bread (vms_buf + test_len, (bfd_size_type) remaining, abfd) !=
- (bfd_size_type) remaining)
+
+ if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
- PRIV (vms_rec) = vms_buf + test_start;
+
+ /* Reset the record pointer. */
+ PRIV (vms_rec) = PRIV (vms_buf);
+ maybe_adjust_record_pointer_for_object (abfd);
}
#if VMS_DEBUG
- vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length));
+ vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
#endif
- return PRIV (rec_length);
+ return PRIV (rec_size);
}
-/* Get next vms record from file
- update vms_rec and rec_length to new (remaining) values. */
+/* Implement step #2 of the record reading procedure for images.
+ Return the size of the record or 0 on failure. */
-int
-_bfd_vms_next_record (bfd * abfd)
+static int
+vms_get_remaining_image_record (bfd *abfd, int read_so_far)
{
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
- PRIV (rec_length), PRIV (rec_size));
-#endif
+ unsigned int to_read;
+ int remaining;
- if (PRIV (rec_length) > 0)
- PRIV (vms_rec) += PRIV (rec_size);
- else
+ /* Extract record size. */
+ PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
+
+ if (PRIV (rec_size) > PRIV (buf_size))
{
- if (_bfd_vms_get_record (abfd) <= 0)
- return -1;
+ PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size));
+
+ if (PRIV (vms_buf) == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return 0;
+ }
+
+ PRIV (buf_size) = PRIV (rec_size);
}
- if (!PRIV (vms_rec) || !PRIV (vms_buf)
- || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
- return -1;
+ /* Read the remaining record. */
+ remaining = PRIV (rec_size) - read_so_far;
+ to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
- if (PRIV (is_vax))
+ while (remaining > 0)
{
- PRIV (rec_type) = *(PRIV (vms_rec));
- PRIV (rec_size) = PRIV (rec_length);
- }
- else
- _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
- &PRIV (rec_size));
+ if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return 0;
+ }
- PRIV (rec_length) -= PRIV (rec_size);
+ read_so_far += to_read;
+ remaining -= to_read;
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
- PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
- PRIV (rec_type));
-#endif
+ /* Eat trailing 0xff's. */
+ if (remaining > 0)
+ while (PRIV (vms_buf) [read_so_far - 1] == 0xff)
+ read_so_far--;
+
+ to_read = MIN (VMS_BLOCK_SIZE, remaining);
+ }
- return PRIV (rec_type);
+ /* Reset the record pointer. */
+ PRIV (vms_rec) = PRIV (vms_buf);
+
+ return PRIV (rec_size);
}
-\f
-/* Copy sized string (string with fixed length) to new allocated area
- size is string length (size of record) */
+
+/* Copy sized string (string with fixed size) to new allocated area
+ size is string size (size of record) */
char *
_bfd_vms_save_sized_string (unsigned char *str, int size)
return newstr;
}
-/* Copy counted string (string with length at first byte) to new allocated area
- ptr points to length byte on entry */
+/* Copy counted string (string with size at first byte) to new allocated area
+ ptr points to size byte on entry */
char *
_bfd_vms_save_counted_string (unsigned char *ptr)
return value;
}
\f
-/* 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];
-}
-\f
/* Object output routines. */
/* Begin new record or record header
write 2 bytes rectype
write 2 bytes record length (filled in at flush)
- write 2 bytes header type (ommitted if rechead == -1). */
+ write 2 bytes header type (ommitted if rechead == -1). */
void
_bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
if (PRIV (push_level) == 0)
{
- if (0
-#ifndef VMS
- /* Write length first, see FF_FOREIGN in the input routines. */
- || fwrite (PRIV (output_buf) + 2, 2, 1,
- (FILE *) abfd->iostream) != 1
-#endif
- || (real_size != 0
- && fwrite (PRIV (output_buf), (size_t) real_size, 1,
- (FILE *) abfd->iostream) != 1))
- /* FIXME: Return error status. */
- abort ();
-
+ /* File is open in undefined (UDF) format on VMS, but ultimately will be
+ converted to variable length (VAR) format. VAR format has a length
+ word first which must be explicitly output in UDF format. */
+ bfd_bwrite (PRIV (output_buf) + 2, 2, abfd);
+ bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd);
PRIV (output_size) = 0;
}
else
if (symbol == 0)
return symbol;
symbol->name = name;
- symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
+ symbol->section = (asection *)(unsigned long)-1;
return symbol;
}
/* vms-tir.c -- BFD back-end for VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007,
+ 2008, 2009 Free Software Foundation, Inc.
TIR record handling functions
ETIR record handling functions
- go and read the openVMS linker manual (esp. appendix B)
+ Go and read the openVMS linker manual (esp. appendix B)
if you don't know what's going on here :-)
Written by Klaus K"ampf (kkaempf@rmi.de)
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)
#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);
+
\f
static int
check_section (bfd * abfd, int size)
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
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++;
}
if (PRIV (is_vax) && check_section (abfd, 1))
return;
+ if (PRIV (dst_section))
+ dst_check_allocation (abfd, 1);
+
*PRIV (image_ptr)++ = (value & 0xff);
}
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;
}
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;
}
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;
}
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";
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";
case ETIR_S_C_STC_BOH_GBL: return "ETIR_S_C_STC_BOH_GBL";
case ETIR_S_C_STC_BOH_PS: return "ETIR_S_C_STC_BOH_PS";
case ETIR_S_C_STC_NBH_GBL: return "ETIR_S_C_STC_NBH_GBL";
+ case ETIR_S_C_CTL_SETRB: return "ETIR_S_C_CTL_SETRB";
+ case ETIR_S_C_STC_LP_PSB: return "ETIR_S_C_STC_LP_PSB";
+ case ETIR_S_C_CTL_DFLOC: return "ETIR_S_C_CTL_DFLOC";
+ case ETIR_S_C_CTL_STLOC: return "ETIR_S_C_CTL_STLOC";
+ case ETIR_S_C_CTL_STKDL: return "ETIR_S_C_CTL_STKDL";
default:
/* These names have not yet been added to this switch statement. */
- abort ();
+ (*_bfd_error_handler) (_("unknown ETIR command %d"), cmd);
}
+
+ return NULL;
}
#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
/* etir_sta
- vms stack commands
+ Vms stack commands.
- handle sta_xxx commands in etir section
- ptr points to data area in record
+ Handle sta_xxx commands in etir section,
+ ptr points to data area in record.
- see table B-8 of the openVMS linker manual. */
+ See table B-8 of the openVMS linker manual. */
static bfd_boolean
-etir_sta (bfd * abfd, int cmd, unsigned char *ptr)
+etir_sta (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
{
#if VMS_DEBUG
_bfd_vms_debug (5, "etir_sta %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
switch (cmd)
{
- /* stack global
+ /* Stack global
arg: cs symbol name
stack 32 bit value of symbol (high bits set to 0). */
else
_bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1);
}
+ *quarter_relocs = 1;
break;
- /* stack longword
+ /* Stack longword
arg: lw value
stack 32 bit value, sign extend to 64 bit. */
case ETIR_S_C_STA_LW:
_bfd_vms_push (abfd, (uquad) bfd_getl32 (ptr), -1);
+ /* This one is special as it is both part of the section header
+ and of the ALPHA_R_REFLONG relocation. */
+ if (bfd_getl16 (ptr - 4 + bfd_getl16 (ptr - 2)) == ETIR_S_C_CTL_DFLOC)
+ *quarter_relocs = 0;
+ else if (*quarter_relocs)
+ *quarter_relocs += 1;
+ else
+ *quarter_relocs = 2;
break;
- /* stack global
+ /* Stack quadword
arg: qw value
stack 64 bit value of symbol. */
case ETIR_S_C_STA_QW:
_bfd_vms_push (abfd, (uquad) bfd_getl64 (ptr), -1);
+ if (*quarter_relocs)
+ *quarter_relocs += 1;
+ else
+ *quarter_relocs = 2;
break;
- /* stack psect base plus quadword offset
+ /* Stack psect base plus quadword offset
arg: lw section index
qw signed quadword offset (low 32 bits)
- stack qw argument and section index
+ Stack qw argument and section index
(see ETIR_S_C_STO_OFF, ETIR_S_C_CTL_SETRB). */
case ETIR_S_C_STA_PQ:
{
uquad dummy;
- unsigned int psect;
+ int psect;
psect = bfd_getl32 (ptr);
- if (psect >= PRIV (section_count))
+ if ((unsigned int) psect >= PRIV (section_count))
{
(*_bfd_error_handler) (_("bad section index in %s"),
cmd_name (cmd));
dummy = bfd_getl64 (ptr + 4);
_bfd_vms_push (abfd, dummy, (int) psect);
}
+ /* This one is special as it is both part of the section header
+ and of the ALPHA_R_REFLONG and ALPHA_R_REFQUAD relocations. */
+ if (bfd_getl16 (ptr - 4 + bfd_getl16 (ptr - 2)) == ETIR_S_C_CTL_SETRB)
+ *quarter_relocs = 0;
+ else
+ *quarter_relocs = 2;
break;
case ETIR_S_C_STA_LI:
case ETIR_S_C_STA_MOD:
case ETIR_S_C_STA_CKARG:
(*_bfd_error_handler) (_("unsupported STA cmd %s"), cmd_name (cmd));
+ *quarter_relocs = 0;
return FALSE;
- break;
default:
(*_bfd_error_handler) (_("reserved STA cmd %d"), cmd);
+ *quarter_relocs = 0;
return FALSE;
- break;
}
+
#if VMS_DEBUG
_bfd_vms_debug (5, "etir_sta true\n");
#endif
+
return TRUE;
}
see table B-9 of the openVMS linker manual. */
static bfd_boolean
-etir_sto (bfd * abfd, int cmd, unsigned char *ptr)
+etir_sto (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
{
uquad dummy;
int psect;
#if VMS_DEBUG
_bfd_vms_debug (5, "etir_sto %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
switch (cmd)
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
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
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
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
while (dummy-- > 0)
image_dump (abfd, ptr+4, size, 0);
}
+ *quarter_relocs = 0;
break;
/* Store global: write symbol value
entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
name, FALSE, FALSE);
if (entry == NULL)
- {
- (*_bfd_error_handler) (_("%s: no symbol \"%s\""),
- cmd_name (cmd), name);
- return FALSE;
- }
+ /* FIXME, reloc. */
+ image_write_q (abfd, (uquad) (0));
else
/* FIXME, reloc. */
image_write_q (abfd, (uquad) (entry->symbol->value));
}
+ *quarter_relocs = 4;
break;
/* Store code address: write address of entry point
entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
name, FALSE, FALSE);
if (entry == NULL)
- {
- (*_bfd_error_handler) (_("%s: no symbol \"%s\""),
- cmd_name (cmd), name);
- return FALSE;
- }
+ /* FIXME, reloc. */
+ image_write_q (abfd, (uquad) (0));
else
/* FIXME, reloc. */
image_write_q (abfd, (uquad) (entry->symbol->value));
}
+ *quarter_relocs = 4;
break;
/* Store offset to psect: pop stack, add low 32 bits to base of psect
q += (PRIV (sections)[psect1])->vma;
image_write_q (abfd, q);
}
+ *quarter_relocs += 2;
break;
/* Store immediate
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
/* FIXME, reloc. */
image_write_l (abfd, (unsigned long) (entry->symbol->value));
}
+ *quarter_relocs = 4;
break;
case ETIR_S_C_STO_RB:
case ETIR_S_C_STO_AB:
case ETIR_S_C_STO_LP_PSB:
(*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd));
- break;
+ *quarter_relocs = 0;
+ return FALSE;
case ETIR_S_C_STO_HINT_GBL:
case ETIR_S_C_STO_HINT_PS:
(*_bfd_error_handler) (_("%s: not implemented"), cmd_name (cmd));
- break;
+ *quarter_relocs = 0;
+ return FALSE;
default:
(*_bfd_error_handler) (_("reserved STO cmd %d"), cmd);
- break;
+ *quarter_relocs = 0;
+ return FALSE;
}
return TRUE;
see table B-10 of the openVMS linker manual. */
static bfd_boolean
-etir_opr (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED)
+etir_opr (bfd *abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED,
+ int *quarter_relocs)
{
long op1, op2;
#if VMS_DEBUG
_bfd_vms_debug (5, "etir_opr %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
+ /* No relocation uses OPR commands except ETIR_S_C_OPR_ADD. */
+ if (cmd == ETIR_S_C_OPR_ADD)
+ *quarter_relocs += 1;
+ else
+ *quarter_relocs = 0;
+
switch (cmd)
{
case ETIR_S_C_OPR_NOP: /* No-op. */
case ETIR_S_C_OPR_REDEF: /* Redefine symbol to current location. */
case ETIR_S_C_OPR_DFLIT: /* Define a literal. */
(*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd));
- break;
+ return FALSE;
case ETIR_S_C_OPR_SEL: /* Select. */
if ((long) _bfd_vms_pop (abfd, NULL) & 0x01L)
default:
(*_bfd_error_handler) (_("reserved OPR cmd %d"), cmd);
- break;
+ return FALSE;
}
return TRUE;
See table B-11 of the openVMS linker manual. */
static bfd_boolean
-etir_ctl (bfd * abfd, int cmd, unsigned char *ptr)
+etir_ctl (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
{
- uquad dummy;
+ uquad dummy;
int psect;
#if VMS_DEBUG
_bfd_vms_debug (5, "etir_ctl %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
+ /* No relocation uses CTL commands. */
+ *quarter_relocs = 0;
+
switch (cmd)
{
/* Det relocation base: pop stack, set image location counter
arg: none. */
case ETIR_S_C_CTL_DFLOC:
dummy = _bfd_vms_pop (abfd, NULL);
- /* FIXME */
+ dst_define_location (abfd, dummy);
break;
/* Set location: pop index, restore location counter from index
arg: none. */
case ETIR_S_C_CTL_STLOC:
- dummy = _bfd_vms_pop (abfd, &psect);
- /* FIXME */
+ dummy = _bfd_vms_pop (abfd, NULL);
+ dst_restore_location (abfd, dummy);
break;
/* Stack defined location: pop index, push location counter from index
arg: none. */
case ETIR_S_C_CTL_STKDL:
- dummy = _bfd_vms_pop (abfd, &psect);
- /* FIXME. */
+ dummy = _bfd_vms_pop (abfd, NULL);
+ _bfd_vms_push (abfd, dst_retrieve_location (abfd, dummy), -1);
break;
default:
(*_bfd_error_handler) (_("reserved CTL cmd %d"), cmd);
- break;
+ return FALSE;
}
+
return TRUE;
}
See table B-12 and B-13 of the openVMS linker manual. */
static bfd_boolean
-etir_stc (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED)
+etir_stc (bfd *abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED,
+ int *quarter_relocs)
{
#if VMS_DEBUG
_bfd_vms_debug (5, "etir_stc %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
switch (cmd)
/* 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
qw offset. */
case ETIR_S_C_STC_PS:
(*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd));
+ *quarter_relocs = 0;
+ return FALSE;
+
+ /* 201 Store-conditional Linkage Pair with Procedure Signature
+ arg: lw linkage index
+ cs procedure name
+ by signature length
+ da signature. */
+
+ case ETIR_S_C_STC_LP_PSB:
+ image_inc_ptr (abfd, (uquad) 16); /* skip entry,procval */
+ *quarter_relocs = 4;
break;
/* 205 Store-conditional NOP at address of global
arg: none. */
case ETIR_S_C_STC_NOP_GBL:
-
- /* 206 Store-conditional NOP at pect + offset
- arg: none. */
- case ETIR_S_C_STC_NOP_PS:
+ /* ALPHA_R_NOP */
/* 207 Store-conditional BSR at global address
arg: none. */
- case ETIR_S_C_STC_BSR_GBL:
- /* 208 Store-conditional BSR at pect + offset
- arg: none. */
- case ETIR_S_C_STC_BSR_PS:
+ case ETIR_S_C_STC_BSR_GBL:
+ /* ALPHA_R_BSR */
/* 209 Store-conditional LDA at global address
arg: none. */
- case ETIR_S_C_STC_LDA_GBL:
- /* 210 Store-conditional LDA at psect + offset
- arg: none. */
- case ETIR_S_C_STC_LDA_PS:
+ case ETIR_S_C_STC_LDA_GBL:
+ /* ALPHA_R_LDA */
/* 211 Store-conditional BSR or Hint at global address
arg: none. */
- case ETIR_S_C_STC_BOH_GBL:
- /* 212 Store-conditional BSR or Hint at pect + offset
- arg: none. */
- case ETIR_S_C_STC_BOH_PS:
+ case ETIR_S_C_STC_BOH_GBL:
+ *quarter_relocs = 4;
+ break;
/* 213 Store-conditional NOP,BSR or HINT at global address
arg: none. */
+
case ETIR_S_C_STC_NBH_GBL:
- /* 214 Store-conditional NOP,BSR or HINT at psect + offset
+ /* 206 Store-conditional NOP at pect + offset
+ arg: none. */
+
+ case ETIR_S_C_STC_NOP_PS:
+
+ /* 208 Store-conditional BSR at pect + offset
+ arg: none. */
+
+ case ETIR_S_C_STC_BSR_PS:
+
+ /* 210 Store-conditional LDA at psect + offset
+ arg: none. */
+
+ case ETIR_S_C_STC_LDA_PS:
+
+ /* 212 Store-conditional BSR or Hint at pect + offset
+ arg: none. */
+
+ case ETIR_S_C_STC_BOH_PS:
+
+ /* 214 Store-conditional NOP, BSR or HINT at psect + offset
arg: none. */
case ETIR_S_C_STC_NBH_PS:
- /* FIXME */
- break;
+ (*_bfd_error_handler) ("%s: not supported", cmd_name (cmd));
+ *quarter_relocs = 0;
+ return FALSE;
default:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "reserved STC cmd %d", cmd);
-#endif
- break;
+ (*_bfd_error_handler) (_("reserved STC cmd %d"), cmd);
+ *quarter_relocs = 0;
+ return FALSE;
}
+
return TRUE;
}
/* tir_sta
- vax stack commands
+ Vax stack commands.
- Handle sta_xxx commands in tir section
- ptr points to data area in record
+ Handle sta_xxx commands in tir section,
+ ptr points to data area in record.
See table 7-3 of the VAX/VMS linker manual. */
by signed byte offset. */
{
unsigned long dummy;
- unsigned int psect;
+ int psect;
if (cmd == TIR_S_C_STA_PB)
psect = *ptr++;
ptr += 2;
}
- if (psect >= PRIV (section_count))
+ if ((unsigned int) psect >= PRIV (section_count))
alloc_section (abfd, psect);
dummy = (long) *ptr++;
dummy += (PRIV (sections)[psect])->vma;
- _bfd_vms_push (abfd, (uquad) dummy, (int) psect);
+ _bfd_vms_push (abfd, (uquad) dummy, psect);
}
break;
sh signed short offset. */
{
unsigned long dummy;
- unsigned int psect;
+ int psect;
if (cmd == TIR_S_C_STA_PW)
psect = *ptr++;
ptr += 2;
}
- if (psect >= PRIV (section_count))
+ if ((unsigned int) psect >= PRIV (section_count))
alloc_section (abfd, psect);
dummy = bfd_getl16 (ptr); ptr+=2;
dummy += (PRIV (sections)[psect])->vma;
- _bfd_vms_push (abfd, (uquad) dummy, (int) psect);
+ _bfd_vms_push (abfd, (uquad) dummy, psect);
}
break;
lw signed longword offset. */
{
unsigned long dummy;
- unsigned int psect;
+ int psect;
if (cmd == TIR_S_C_STA_PL)
psect = *ptr++;
ptr += 2;
}
- if (psect >= PRIV (section_count))
+ if ((unsigned int) psect >= PRIV (section_count))
alloc_section (abfd, psect);
dummy = bfd_getl32 (ptr); ptr += 4;
dummy += (PRIV (sections)[psect])->vma;
- _bfd_vms_push (abfd, (uquad) dummy, (int) psect);
+ _bfd_vms_push (abfd, (uquad) dummy, psect);
}
break;
tir_ctl (bfd * abfd, unsigned char *ptr)
{
unsigned long dummy;
- unsigned int psect;
+ int psect;
#if VMS_DEBUG
_bfd_vms_debug (5, "tir_ctl %d\n", *ptr);
case TIR_S_C_CTL_SETRB:
/* Set relocation base: pop stack, set image location counter
arg: none. */
- dummy = _bfd_vms_pop (abfd, (int *) &psect);
- if (psect >= PRIV (section_count))
+ dummy = _bfd_vms_pop (abfd, &psect);
+ if ((unsigned int) psect >= PRIV (section_count))
alloc_section (abfd, psect);
- image_set_ptr (abfd, (int) psect, (uquad) dummy);
+ image_set_ptr (abfd, psect, (uquad) dummy);
break;
case TIR_S_C_CTL_AUGRB:
case TIR_S_C_CTL_STLOC:
/* Set location: pop index, restore location counter from index
arg: none. */
- dummy = _bfd_vms_pop (abfd, (int *) &psect);
+ dummy = _bfd_vms_pop (abfd, &psect);
(*_bfd_error_handler) (_("%s: not fully implemented"),
tir_cmd_name (ptr[-1]));
break;
case TIR_S_C_CTL_STKDL:
/* Stack defined location: pop index, push location counter from index
arg: none. */
- dummy = _bfd_vms_pop (abfd, (int *) &psect);
+ dummy = _bfd_vms_pop (abfd, &psect);
(*_bfd_error_handler) (_("%s: not fully implemented"),
tir_cmd_name (ptr[-1]));
break;
static unsigned char *
tir_cmd (bfd * abfd, unsigned char *ptr)
{
- struct
+ static const struct
{
int mincod;
int maxcod;
#if VMS_DEBUG
_bfd_vms_debug (4, "tir_cmd %d/%x\n", *ptr, *ptr);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
if (*ptr & 0x80)
/* Handle command from ETIR section. */
static int
-etir_cmd (bfd * abfd, int cmd, unsigned char *ptr)
+etir_cmd (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
{
- static struct
+ static const struct
{
int mincod;
int maxcod;
- bfd_boolean (*explain) (bfd *, int, unsigned char *);
+ bfd_boolean (*explain) (bfd *, int, unsigned char *, int *);
}
etir_table[] =
{
int i = 0;
#if VMS_DEBUG
- _bfd_vms_debug (4, "etir_cmd %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (int) ptr);
+ _bfd_vms_debug (4, "etir_cmd: %s(%d)\n", cmd_name (cmd), cmd);
+ _bfd_hexdump (8, ptr, 16, (long) ptr);
#endif
while (etir_table[i].mincod >= 0)
if ( (etir_table[i].mincod <= cmd)
&& (cmd <= etir_table[i].maxcod))
{
- if (!etir_table[i].explain (abfd, cmd, ptr))
+ if (!etir_table[i].explain (abfd, cmd, ptr, quarter_relocs))
return -1;
break;
}
}
#if VMS_DEBUG
- _bfd_vms_debug (4, "etir_cmd: = 0\n");
+ _bfd_vms_debug (4, "etir_cmd: result = 0\n");
#endif
return 0;
}
static int
analyze_etir (bfd * abfd, unsigned char *ptr, unsigned int length)
{
- int cmd;
- unsigned char *maxptr;
+ unsigned char *maxptr = ptr + length;
+ /* Relocations are made of 1, 2 or 4 ETIR commands.
+ We therefore count them using quarters. */
+ int quarter_relocs = 0;
int result = 0;
#if VMS_DEBUG
_bfd_vms_debug (3, "analyze_etir: %d bytes\n", length);
#endif
- maxptr = ptr + length;
-
while (ptr < maxptr)
{
- cmd = bfd_getl16 (ptr);
- length = bfd_getl16 (ptr + 2);
- result = etir_cmd (abfd, cmd, ptr+4);
+ int cmd = bfd_getl16 (ptr);
+ int cmd_length = bfd_getl16 (ptr + 2);
+ result = etir_cmd (abfd, cmd, ptr + 4, &quarter_relocs);
if (result != 0)
break;
- ptr += length;
+
+ /* If we have a relocation, we record its length to size
+ future buffers and bump the reloc count of the section. */
+ if (quarter_relocs)
+ {
+ vms_section_data (PRIV (image_section))->reloc_size += cmd_length;
+ abfd->flags |= HAS_RELOC;
+
+ if (quarter_relocs == 4)
+ {
+ PRIV (image_section)->reloc_count++;
+
+#if VMS_DEBUG
+ _bfd_vms_debug (4, "-> reloc %d at 0x%x\n",
+ PRIV (image_section)->reloc_count-1,
+ ptr - (maxptr - length));
+#endif
+
+ quarter_relocs = 0;
+ }
+ else if (quarter_relocs > 4)
+ {
+
+#if VMS_DEBUG
+ _bfd_vms_debug (4, "Reloc count error (%d) in section %s\n",
+ PRIV (image_section)->reloc_count,
+ PRIV (image_section)->name);
+#endif
+
+ quarter_relocs = 0;
+ }
+ }
+
+ /* If we have a Store Immediate, we reserve space for the
+ count argument. */
+ else if (cmd == ETIR_S_C_STO_IMM)
+ vms_section_data (PRIV (image_section))->reloc_size
+ += ETIR_S_C_HEADER_SIZE + 4;
+
+ ptr += cmd_length;
}
#if VMS_DEBUG
- _bfd_vms_debug (3, "analyze_etir: = %d\n", result);
+ _bfd_vms_debug (3, "analyze_etir: result = %d\n", result);
#endif
return result;
switch (objtype)
{
case EOBJ_S_C_ETIR:
- PRIV (vms_rec) += 4; /* Skip type, size. */
- PRIV (rec_size) -= 4;
+ PRIV (vms_rec) += ETIR_S_C_HEADER_SIZE;
+ PRIV (rec_size) -= ETIR_S_C_HEADER_SIZE;
result = analyze_etir (abfd, PRIV (vms_rec), (unsigned) PRIV (rec_size));
break;
case OBJ_S_C_TIR:
return result;
}
-/* Process EDBG record
- Return 0 on success, -1 on error
-
- Not implemented yet. */
+ /* Slurp relocs from ETIR sections and (temporarily) save them
+ in the per-section reloc buffer. */
int
-_bfd_vms_slurp_dbg (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
+_bfd_vms_slurp_relocs (bfd *abfd)
{
+ struct vms_section_data_struct *vsd;
+ unsigned char *begin = PRIV (vms_rec) + 4;
+ unsigned char *end = PRIV (vms_rec) + PRIV (rec_size);
+ unsigned char *ptr;
+ int cmd, length, slurped_length;
+
#if VMS_DEBUG
- _bfd_vms_debug (2, "DBG/EDBG\n");
+ _bfd_vms_debug (3, "_bfd_vms_slurp_relocs: %d bytes\n", PRIV (rec_size));
+#endif
+
+ for (ptr = begin; ptr < end; ptr += length)
+ {
+ cmd = bfd_getl16 (ptr);
+ length = bfd_getl16 (ptr + 2);
+ slurped_length = length;
+
+ switch (cmd)
+ {
+ case ETIR_S_C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */
+ /* This one is special as it is both part of the section header
+ and of the ALPHA_R_REFLONG and ALPHA_R_REFQUAD relocations. */
+ if (bfd_getl16 (ptr + length) == ETIR_S_C_CTL_SETRB)
+ {
+ int psect = bfd_getl32 (ptr + ETIR_S_C_HEADER_SIZE);
+ PRIV (image_section) = PRIV (sections)[psect];
+ continue;
+ }
+
+ case ETIR_S_C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */
+ /* ALPHA_R_REFQUAD und_section, step 1 */
+ break;
+
+ case ETIR_S_C_STA_LW: /* ALPHA_R_REFLONG und_section, step 2 */
+ /* ALPHA_R_REFLONG abs_section, step 1 */
+ /* This one is special as it is both part of the section header
+ and of the ALPHA_R_REFLONG relocation. */
+ if (bfd_getl16 (ptr + length) == ETIR_S_C_CTL_DFLOC)
+ {
+ PRIV (image_section) = PRIV (dst_section);
+ continue;
+ }
+
+ case ETIR_S_C_STA_QW: /* ALPHA_R_REFQUAD und_section, step 2 */
+ /* ALPHA_R_REFQUAD abs_section, step 1 */
+
+ case ETIR_S_C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */
+ /* ALPHA_R_REFLONG abs_section, step 2 */
+ /* ALPHA_R_REFLONG others, step 2 */
+
+ case ETIR_S_C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */
+ /* ALPHA_R_REFQUAD abs_section, step 2 */
+
+ case ETIR_S_C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */
+
+ case ETIR_S_C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */
+ /* ALPHA_R_REFQUAD und_section, step 3 */
+
+ case ETIR_S_C_STO_CA: /* ALPHA_R_CODEADDR */
+ case ETIR_S_C_STO_GBL: /* ALPHA_R_REFQUAD und_section */
+ case ETIR_S_C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */
+ case ETIR_S_C_STC_LP_PSB: /* ALPHA_R_LINKAGE */
+ case ETIR_S_C_STC_NOP_GBL: /* ALPHA_R_NOP */
+ case ETIR_S_C_STC_BSR_GBL: /* ALPHA_R_BSR */
+ case ETIR_S_C_STC_LDA_GBL: /* ALPHA_R_LDA */
+ case ETIR_S_C_STC_BOH_GBL: /* ALPHA_R_BOH */
+ break;
+
+ case ETIR_S_C_STO_IMM:
+ if (PRIV (image_section)->reloc_count == 0)
+ continue;
+ /* This is not a relocation, but we nevertheless slurp the
+ count argument. We'll use it to compute the addresses
+ of the relocations. */
+ slurped_length = ETIR_S_C_HEADER_SIZE + 4;
+ break;
+
+ default:
+ continue;
+ }
+
+ vsd = vms_section_data (PRIV (image_section));
+ memcpy (vsd->reloc_stream + vsd->reloc_offset, ptr, slurped_length);
+ vsd->reloc_offset += slurped_length;
+ if (vsd->reloc_offset > vsd->reloc_size)
+ {
+ (*_bfd_error_handler) (_("Reloc size error in section %s"),
+ PRIV (image_section)->name);
+ return -1;
+ }
+ }
+
+#if VMS_DEBUG
+ _bfd_vms_debug (3, "_bfd_vms_slurp_relocs: result = 0\n");
#endif
- abfd->flags |= (HAS_DEBUG | HAS_LINENO);
return 0;
}
-/* Process ETBT record
- Return 0 on success, -1 on error
-
- Not implemented yet. */
+/* Decode relocs from the reloc buffer of the specified section
+ and internalize them in the specified buffer. */
int
-_bfd_vms_slurp_tbt (bfd * abfd ATTRIBUTE_UNUSED,
- int objtype ATTRIBUTE_UNUSED)
+_bfd_vms_decode_relocs (bfd *abfd, arelent *relocs, asection *section,
+ asymbol **symbols ATTRIBUTE_UNUSED)
{
+ int saved_cmd, saved_sym_offset, saved_sec_offset, saved_addend_offset;
+ int cmd, sym_offset, sec_offset, address_offset, addend_offset;
+ struct vms_section_data_struct *vsd = vms_section_data (section);
+ bfd_reloc_code_real_type reloc_code;
+ vms_symbol_entry *entry;
+ bfd_vma vaddr = 0;
+ unsigned char *begin = vsd->reloc_stream;
+ unsigned char *end = vsd->reloc_stream + vsd->reloc_size;
+ unsigned char *ptr, *arg_ptr;
+ const char *name;
+ int length;
+
#if VMS_DEBUG
- _bfd_vms_debug (2, "TBT/ETBT\n");
+ _bfd_vms_debug (3, "_bfd_vms_decode_relocs: %d bytes\n", vsd->reloc_size);
+#endif
+
+ #define PUSH_CMD() \
+ { \
+ saved_cmd = cmd; \
+ saved_sym_offset = sym_offset - length; \
+ saved_sec_offset = sec_offset - length; \
+ saved_addend_offset = addend_offset - length; \
+ continue; \
+ }
+
+ #define POP_CMD() \
+ { \
+ cmd = saved_cmd; \
+ saved_cmd = ETIR_S_C_MAXSTCCOD + 1; \
+ sym_offset = saved_sym_offset; \
+ sec_offset = saved_sec_offset; \
+ addend_offset= saved_addend_offset; \
+ }
+
+ #define CMD_PUSHED (saved_cmd != ETIR_S_C_MAXSTCCOD + 1)
+
+ #define NO_OFFSET -128
+
+ saved_cmd = ETIR_S_C_MAXSTCCOD + 1;
+ saved_sym_offset = NO_OFFSET;
+ saved_sec_offset = NO_OFFSET;
+ saved_addend_offset = NO_OFFSET;
+
+ for (ptr = begin; ptr < end; ptr += length)
+ {
+ cmd = bfd_getl16 (ptr);
+ length = bfd_getl16 (ptr + 2);
+
+ arg_ptr = ptr + ETIR_S_C_HEADER_SIZE;
+ sym_offset = NO_OFFSET;
+ sec_offset = NO_OFFSET;
+ address_offset = NO_OFFSET;
+ addend_offset = NO_OFFSET;
+
+ switch (cmd)
+ {
+ case ETIR_S_C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */
+ /* ALPHA_R_REFQUAD und_section, step 1 */
+ sym_offset = 0;
+ PUSH_CMD ()
+
+ case ETIR_S_C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */
+ sec_offset = 0;
+ addend_offset = 4;
+ PUSH_CMD ()
+
+ case ETIR_S_C_STA_LW: /* ALPHA_R_REFLONG abs_section, step 1 */
+ /* ALPHA_R_REFLONG und_section, step 2 */
+ if (CMD_PUSHED)
+ {
+ POP_CMD ()
+ if (cmd != ETIR_S_C_STA_GBL)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ cmd_name (cmd),
+ cmd_name (ETIR_S_C_STA_LW));
+ return 0;
+ }
+ cmd = ETIR_S_C_STA_LW;
+ }
+ addend_offset = 0;
+ PUSH_CMD ()
+
+ case ETIR_S_C_STA_QW: /* ALPHA_R_REFQUAD abs_section, step 1 */
+ /* ALPHA_R_REFQUAD und_section, step 2 */
+ if (CMD_PUSHED)
+ {
+ POP_CMD ()
+ if (cmd != ETIR_S_C_STA_GBL)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ cmd_name (cmd),
+ cmd_name (ETIR_S_C_STA_QW));
+ return 0;
+ }
+ cmd = ETIR_S_C_STA_QW;
+ }
+ addend_offset = 0;
+ PUSH_CMD ()
+
+ case ETIR_S_C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */
+ /* ALPHA_R_REFLONG abs_section, step 2 */
+ /* ALPHA_R_REFLONG others, step 2 */
+ POP_CMD ()
+ if (cmd != ETIR_S_C_OPR_ADD
+ && cmd != ETIR_S_C_STA_LW
+ && cmd != ETIR_S_C_STA_PQ)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ cmd_name (cmd), cmd_name (ETIR_S_C_STO_LW));
+ return 0;
+ }
+ reloc_code = BFD_RELOC_32;
+ break;
+
+ case ETIR_S_C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */
+ /* ALPHA_R_REFQUAD abs_section, step 2 */
+ POP_CMD ()
+ if (cmd != ETIR_S_C_OPR_ADD && cmd != ETIR_S_C_STA_QW)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ cmd_name (cmd), cmd_name (ETIR_S_C_STO_QW));
+ return 0;
+ }
+ reloc_code = BFD_RELOC_64;
+ break;
+
+ case ETIR_S_C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */
+ POP_CMD ()
+ if (cmd != ETIR_S_C_STA_PQ)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ cmd_name (cmd), cmd_name (ETIR_S_C_STO_OFF));
+ return 0;
+ }
+ reloc_code = BFD_RELOC_64;
+ break;
+
+ case ETIR_S_C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */
+ /* ALPHA_R_REFQUAD und_section, step 3 */
+ POP_CMD ()
+ if (cmd != ETIR_S_C_STA_LW && cmd != ETIR_S_C_STA_QW)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ cmd_name (cmd), cmd_name (ETIR_S_C_OPR_ADD));
+ return 0;
+ }
+ cmd = ETIR_S_C_OPR_ADD;
+ PUSH_CMD ()
+
+ case ETIR_S_C_STO_CA: /* ALPHA_R_CODEADDR */
+ reloc_code = BFD_RELOC_ALPHA_CODEADDR;
+ sym_offset = 0;
+ break;
+
+ case ETIR_S_C_STO_GBL: /* ALPHA_R_REFQUAD und_section */
+ reloc_code = BFD_RELOC_64;
+ sym_offset = 0;
+ break;
+
+ case ETIR_S_C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */
+ reloc_code = BFD_RELOC_32;
+ sym_offset = 0;
+ break;
+
+ case ETIR_S_C_STC_LP_PSB: /* ALPHA_R_LINKAGE */
+ reloc_code = BFD_RELOC_ALPHA_LINKAGE;
+ sym_offset = 4;
+ break;
+
+ case ETIR_S_C_STC_NOP_GBL: /* ALPHA_R_NOP */
+ reloc_code = BFD_RELOC_ALPHA_NOP;
+ goto call_reloc;
+
+ case ETIR_S_C_STC_BSR_GBL: /* ALPHA_R_BSR */
+ reloc_code = BFD_RELOC_ALPHA_BSR;
+ goto call_reloc;
+
+ case ETIR_S_C_STC_LDA_GBL: /* ALPHA_R_LDA */
+ reloc_code = BFD_RELOC_ALPHA_LDA;
+ goto call_reloc;
+
+ case ETIR_S_C_STC_BOH_GBL: /* ALPHA_R_BOH */
+ reloc_code = BFD_RELOC_ALPHA_BOH;
+ goto call_reloc;
+
+ call_reloc:
+ sym_offset = 32;
+ address_offset = 8;
+ addend_offset = 24;
+ break;
+
+ case ETIR_S_C_STO_IMM:
+ vaddr += bfd_getl32 (arg_ptr);
+ length = ETIR_S_C_HEADER_SIZE + 4;
+ continue;
+
+ default:
+ continue;
+ }
+
+ relocs->howto = bfd_reloc_type_lookup (abfd, reloc_code);
+
+ if (sym_offset > NO_OFFSET)
+ {
+ name = _bfd_vms_save_counted_string (arg_ptr + sym_offset);
+ entry = (vms_symbol_entry *)
+ bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
+ if (entry == NULL)
+ {
+ (*_bfd_error_handler) (_("Unknown symbol %s in command %s"),
+ name, cmd_name (cmd));
+ relocs->sym_ptr_ptr = NULL;
+ }
+ else
+ /* ??? This is a hack. We should point in 'symbols'. */
+ relocs->sym_ptr_ptr = &entry->symbol;
+ }
+ else if (sec_offset > NO_OFFSET)
+ relocs->sym_ptr_ptr
+ = PRIV (sections)[bfd_getl32 (arg_ptr + sec_offset)]->symbol_ptr_ptr;
+ else
+ relocs->sym_ptr_ptr = NULL;
+
+ if (address_offset > NO_OFFSET)
+ relocs->address = bfd_getl64 (arg_ptr + address_offset);
+ else
+ relocs->address = vaddr;
+
+ if (addend_offset > NO_OFFSET)
+ relocs->addend = bfd_getl64 (arg_ptr + addend_offset);
+ else
+ relocs->addend = 0;
+
+ vaddr += bfd_get_reloc_size (relocs->howto);
+ relocs++;
+ }
+
+ #undef PUSH_CMD
+ #undef POP_CMD
+ #undef NO_OFFSET
+
+#if VMS_DEBUG
+ _bfd_vms_debug (3, "_bfd_vms_decode_relocs: result = 0\n");
#endif
return 0;
return 0;
}
\f
+/* 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
_bfd_vms_output_end (abfd);
}
-/* WRITE ETIR SECTION
-
- This is still under construction and therefore not documented. */
+/* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual
+ address VADDR in section specified by INDEX and NAME. */
static void
-sto_imm (bfd * abfd, vms_section *sptr, bfd_vma vaddr, int index)
+sto_imm (bfd *abfd, bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr,
+ int index, const char *name)
{
- int size;
- int ssize;
- unsigned char *cptr;
+ bfd_size_type size;
#if VMS_DEBUG
- _bfd_vms_debug (8, "sto_imm %d bytes\n", sptr->size);
- _bfd_hexdump (9, sptr->contents, (int) sptr->size, (int) vaddr);
+ _bfd_vms_debug (8, "sto_imm %d bytes\n", ssize);
+ _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr);
#endif
- ssize = sptr->size;
- cptr = sptr->contents;
-
while (ssize > 0)
{
/* Try all the rest. */
{
/* Doesn't fit, split ! */
end_etir_record (abfd);
- start_etir_record (abfd, index, vaddr, FALSE);
- /* Get max size. */
- size = _bfd_vms_output_check (abfd, 0);
- /* More than what's left ? */
- if (size > ssize)
+
+ if (name [0] && name[1] == 'v' && !strcmp (name, ".vmsdebug"))
+ start_another_etbt_record (abfd);
+ else
+ start_etir_record (abfd, index, vaddr, FALSE);
+
+ size = _bfd_vms_output_check (abfd, 0); /* get max size */
+ if (size > ssize) /* more than what's left ? */
size = ssize;
}
#endif
vaddr += size;
- ssize -= size;
cptr += size;
+ ssize -= size;
+ }
+}
+
+/* Start ETBT record for section #index at virtual addr offset. */
+
+static void
+start_first_etbt_record (bfd *abfd)
+{
+ _bfd_vms_output_begin (abfd, EOBJ_S_C_ETBT, -1);
+ _bfd_vms_output_push (abfd);
+
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1); /* push start offset */
+ _bfd_vms_output_long (abfd, (unsigned long) 0);
+ _bfd_vms_output_flush (abfd);
+
+ _bfd_vms_output_begin (abfd, ETIR_S_C_CTL_DFLOC, -1); /* start = pop() */
+ _bfd_vms_output_flush (abfd);
+}
+
+static void
+start_another_etbt_record (bfd *abfd)
+{
+ _bfd_vms_output_begin (abfd, EOBJ_S_C_ETBT, -1);
+ _bfd_vms_output_push (abfd);
+}
+
+static void
+etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen)
+{
+ if (_bfd_vms_output_check (abfd, checklen) < 0)
+ {
+ end_etir_record (abfd);
+ if (section->name[0] && section->name[1] == 'v'
+ && !strcmp (section->name, ".vmsdebug"))
+ start_another_etbt_record (abfd);
+ else
+ start_etir_record (abfd, section->index, vaddr, FALSE);
+ }
+}
+
+/* Return whether RELOC must be deferred till the end. */
+
+static int
+defer_reloc_p (arelent *reloc)
+{
+ switch (reloc->howto->type)
+ {
+ case ALPHA_R_NOP:
+ case ALPHA_R_LDA:
+ case ALPHA_R_BSR:
+ case ALPHA_R_BOH:
+ return 1;
+
+ default:
+ return 0;
}
}
_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);
_bfd_vms_output_alignment (abfd, 4);
- nextoffset = 0;
PRIV (vms_linkage_index) = 1;
- /* Dump all other sections. */
- section = abfd->sections;
-
- while (section != NULL)
+ for (section = abfd->sections; section; section = section->next)
{
-
#if VMS_DEBUG
_bfd_vms_debug (4, "writing %d. section '%s' (%d bytes)\n",
section->index, section->name,
(int) (section->size));
#endif
+ if (!(section->flags & SEC_HAS_CONTENTS)
+ || bfd_is_com_section (section))
+ continue;
+
+ if (!section->contents)
+ {
+ bfd_set_error (bfd_error_no_contents);
+ return -1;
+ }
+
+ if (section->name[0]
+ && section->name[1] == 'v'
+ && !strcmp (section->name, ".vmsdebug"))
+ start_first_etbt_record (abfd);
+ else
+ start_etir_record (abfd, section->index, 0, FALSE);
+
if (section->flags & SEC_RELOC)
{
- int i;
+ bfd_vma curr_addr = 0;
+ unsigned char *curr_data = section->contents;
+ bfd_size_type size;
+ int pass2_needed = 0;
+ int pass2_in_progress = 0;
+ unsigned int irel;
+
+ if (section->reloc_count <= 0)
+ (*_bfd_error_handler)
+ (_("SEC_RELOC with no relocs in section %s"), section->name);
- if ((i = section->reloc_count) <= 0)
- (*_bfd_error_handler) (_("SEC_RELOC with no relocs in section %s"),
- section->name);
#if VMS_DEBUG
else
{
- arelent **rptr;
+ int i = section->reloc_count;
+ arelent **rptr = section->orelocation;
_bfd_vms_debug (4, "%d relocations:\n", i);
- rptr = section->orelocation;
while (i-- > 0)
{
- _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, addr %08lx, off %08lx, len %d: %s\n",
+ _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, "
+ "addr %08lx, off %08lx, len %d: %s\n",
(*(*rptr)->sym_ptr_ptr)->name,
(*(*rptr)->sym_ptr_ptr)->section->name,
(long) (*(*rptr)->sym_ptr_ptr)->value,
(*rptr)->address, (*rptr)->addend,
bfd_get_reloc_size ((*rptr)->howto),
- (*rptr)->howto->name);
+ ( *rptr)->howto->name);
rptr++;
}
}
#endif
- }
- if ((section->flags & SEC_HAS_CONTENTS)
- && (! bfd_is_com_section (section)))
- {
- /* Virtual addr in section. */
- bfd_vma vaddr;
-
- sptr = _bfd_get_vms_section (abfd, section->index);
- if (sptr == NULL)
+ new_pass:
+ for (irel = 0; irel < section->reloc_count; irel++)
{
- bfd_set_error (bfd_error_no_contents);
- return -1;
- }
+ struct evax_private_udata_struct *udata;
+ arelent *rptr = section->orelocation [irel];
+ bfd_vma addr = rptr->address;
+ asymbol *sym = *rptr->sym_ptr_ptr;
+ asection *sec = sym->section;
+ int defer = defer_reloc_p (rptr);
+ unsigned int slen;
+ char *hash;
+
+ if (pass2_in_progress)
+ {
+ /* Non-deferred relocs have already been output. */
+ if (!defer)
+ continue;
+ }
+ else
+ {
+ /* Deferred relocs must be output at the very end. */
+ if (defer)
+ {
+ pass2_needed = 1;
+ continue;
+ }
- vaddr = (bfd_vma) (sptr->offset);
+ /* Regular relocs are intertwined with binary data. */
+ if (curr_addr > addr)
+ (*_bfd_error_handler) (_("Size error in section %s"),
+ section->name);
+ size = addr - curr_addr;
+ sto_imm (abfd, size, curr_data, curr_addr,
+ section->index, section->name);
+ curr_data += size;
+ curr_addr += size;
+ }
- start_etir_record (abfd, section->index, (uquad) sptr->offset,
- FALSE);
+ size = bfd_get_reloc_size (rptr->howto);
- while (sptr != NULL)
- {
- /* One STA_PQ, CTL_SETRB per vms_section. */
- if (section->flags & SEC_RELOC)
- {
- /* Check for relocs. */
- arelent **rptr = section->orelocation;
- int i = section->reloc_count;
+ switch (rptr->howto->type)
+ {
+ case ALPHA_R_IGNORE:
+ break;
- for (;;)
+ case ALPHA_R_REFLONG:
+ if (bfd_is_und_section (sym->section))
{
- bfd_size_type addr = (*rptr)->address;
- bfd_size_type len = bfd_get_reloc_size ((*rptr)->howto);
- if (sptr->offset < addr)
- {
- /* Sptr starts before reloc. */
- bfd_size_type before = addr - sptr->offset;
- if (sptr->size <= before)
- {
- /* Complete before. */
- sto_imm (abfd, sptr, vaddr, section->index);
- vaddr += sptr->size;
- break;
- }
- else
- {
- /* Partly before. */
- int after = sptr->size - before;
-
- sptr->size = before;
- sto_imm (abfd, sptr, vaddr, section->index);
- vaddr += sptr->size;
- sptr->contents += before;
- sptr->offset += before;
- sptr->size = after;
- }
- }
- else if (sptr->offset == addr)
+ bfd_vma addend = rptr->addend;
+ slen = strlen ((char *) sym->name);
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ_S_C_SYMSIZ);
+ etir_output_check (abfd, section, curr_addr, slen);
+ if (addend)
{
- /* Sptr starts at reloc. */
- asymbol *sym = *(*rptr)->sym_ptr_ptr;
- asection *sec = sym->section;
-
- switch ((*rptr)->howto->type)
- {
- case ALPHA_R_IGNORE:
- break;
-
- case ALPHA_R_REFLONG:
- {
- if (bfd_is_und_section (sym->section))
- {
- int slen = strlen ((char *) sym->name);
- char *hash;
-
- if (_bfd_vms_output_check (abfd, slen) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_GBL_LW,
- -1);
- hash = (_bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- }
- else if (bfd_is_abs_section (sym->section))
- {
- if (_bfd_vms_output_check (abfd, 16) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STA_LW,
- -1);
- _bfd_vms_output_quad (abfd,
- (uquad) sym->value);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_LW,
- -1);
- _bfd_vms_output_flush (abfd);
- }
- else
- {
- if (_bfd_vms_output_check (abfd, 32) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STA_PQ,
- -1);
- _bfd_vms_output_long (abfd,
- (unsigned long) (sec->index));
- _bfd_vms_output_quad (abfd,
- ((uquad) (*rptr)->addend
- + (uquad) sym->value));
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_LW,
- -1);
- _bfd_vms_output_flush (abfd);
- }
- }
- break;
-
- case ALPHA_R_REFQUAD:
- {
- if (bfd_is_und_section (sym->section))
- {
- int slen = strlen ((char *) sym->name);
- char *hash;
-
- if (_bfd_vms_output_check (abfd, slen) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_GBL,
- -1);
- hash = (_bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- }
- else if (bfd_is_abs_section (sym->section))
- {
- if (_bfd_vms_output_check (abfd, 16) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STA_QW,
- -1);
- _bfd_vms_output_quad (abfd,
- (uquad) sym->value);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_QW,
- -1);
- _bfd_vms_output_flush (abfd);
- }
- else
- {
- if (_bfd_vms_output_check (abfd, 32) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STA_PQ,
- -1);
- _bfd_vms_output_long (abfd,
- (unsigned long) (sec->index));
- _bfd_vms_output_quad (abfd,
- ((uquad) (*rptr)->addend
- + (uquad) sym->value));
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_OFF,
- -1);
- _bfd_vms_output_flush (abfd);
- }
- }
- break;
-
- case ALPHA_R_HINT:
- {
- int hint_size;
- char *hash ATTRIBUTE_UNUSED;
-
- hint_size = sptr->size;
- sptr->size = len;
- sto_imm (abfd, sptr, vaddr, section->index);
- sptr->size = hint_size;
- }
- break;
- case ALPHA_R_LINKAGE:
- {
- char *hash;
-
- if (_bfd_vms_output_check (abfd, 64) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd, section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STC_LP_PSB,
- -1);
- _bfd_vms_output_long (abfd,
- (unsigned long) PRIV (vms_linkage_index));
- PRIV (vms_linkage_index) += 2;
- hash = (_bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_byte (abfd, 0);
- _bfd_vms_output_flush (abfd);
- }
- break;
-
- case ALPHA_R_CODEADDR:
- {
- int slen = strlen ((char *) sym->name);
- char *hash;
- if (_bfd_vms_output_check (abfd, slen) < 0)
- {
- end_etir_record (abfd);
- start_etir_record (abfd,
- section->index,
- vaddr, FALSE);
- }
- _bfd_vms_output_begin (abfd,
- ETIR_S_C_STO_CA,
- -1);
- hash = (_bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- }
- break;
-
- default:
- (*_bfd_error_handler) (_("Unhandled relocation %s"),
- (*rptr)->howto->name);
- break;
- }
-
- vaddr += len;
-
- if (len == sptr->size)
- {
- break;
- }
- else
- {
- sptr->contents += len;
- sptr->offset += len;
- sptr->size -= len;
- i--;
- rptr++;
- }
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_GBL, -1);
+ _bfd_vms_output_counted (abfd, hash);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1);
+ _bfd_vms_output_long (abfd, (unsigned long) addend);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_OPR_ADD, -1);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1);
+ _bfd_vms_output_flush (abfd);
}
else
{
- /* Sptr starts after reloc. */
- i--;
- /* Check next reloc. */
- rptr++;
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_GBL_LW, -1);
+ _bfd_vms_output_counted (abfd, hash);
+ _bfd_vms_output_flush (abfd);
}
+ }
+ else if (bfd_is_abs_section (sym->section))
+ {
+ etir_output_check (abfd, section, curr_addr, 16);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1);
+ _bfd_vms_output_long (abfd, (unsigned long) sym->value);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1);
+ _bfd_vms_output_flush (abfd);
+ }
+ else
+ {
+ etir_output_check (abfd, section, curr_addr, 32);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1);
+ _bfd_vms_output_long (abfd, (unsigned long) sec->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->addend
+ + (uquad) sym->value);
+ _bfd_vms_output_flush (abfd);
+ /* ??? Table B-8 of the OpenVMS Linker Utilily Manual
+ says that we should have a ETIR_S_C_STO_OFF here.
+ But the relocation would not be BFD_RELOC_32 then.
+ This case is very likely unreachable. */
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1);
+ _bfd_vms_output_flush (abfd);
+ }
+ break;
- if (i == 0)
+ case ALPHA_R_REFQUAD:
+ if (bfd_is_und_section (sym->section))
+ {
+ bfd_vma addend = rptr->addend;
+ slen = strlen ((char *) sym->name);
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ_S_C_SYMSIZ);
+ etir_output_check (abfd, section, curr_addr, slen);
+ if (addend)
+ {
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_GBL, -1);
+ _bfd_vms_output_counted (abfd, hash);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_QW, -1);
+ _bfd_vms_output_quad (abfd, (uquad) addend);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_OPR_ADD, -1);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_QW, -1);
+ _bfd_vms_output_flush (abfd);
+ }
+ else
{
- /* All reloc checked. */
- if (sptr->size > 0)
- {
- /* Dump rest. */
- sto_imm (abfd, sptr, vaddr, section->index);
- vaddr += sptr->size;
- }
- break;
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_GBL, -1);
+ _bfd_vms_output_counted (abfd, hash);
+ _bfd_vms_output_flush (abfd);
}
}
+ else if (bfd_is_abs_section (sym->section))
+ {
+ etir_output_check (abfd, section, curr_addr, 16);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_QW, -1);
+ _bfd_vms_output_quad (abfd, (uquad) sym->value);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_QW, -1);
+ _bfd_vms_output_flush (abfd);
+ }
+ else
+ {
+ etir_output_check (abfd, section, curr_addr, 32);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1);
+ _bfd_vms_output_long (abfd, (unsigned long) sec->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->addend
+ + (uquad) sym->value);
+ _bfd_vms_output_flush (abfd);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_OFF, -1);
+ _bfd_vms_output_flush (abfd);
+ }
+ break;
+
+ case ALPHA_R_HINT:
+ sto_imm (abfd, size, curr_data, curr_addr,
+ section->index, section->name);
+ break;
+
+ case ALPHA_R_LINKAGE:
+ etir_output_check (abfd, section, curr_addr, 64);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STC_LP_PSB, -1);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) PRIV (vms_linkage_index));
+ PRIV (vms_linkage_index) += 2;
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ_S_C_SYMSIZ);
+ _bfd_vms_output_counted (abfd, hash);
+ _bfd_vms_output_byte (abfd, 0);
+ _bfd_vms_output_flush (abfd);
+ break;
+
+ case ALPHA_R_CODEADDR:
+ slen = strlen ((char *) sym->name);
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ_S_C_SYMSIZ);
+ etir_output_check (abfd, section, curr_addr, slen);
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STO_CA, -1);
+ _bfd_vms_output_counted (abfd, hash);
+ _bfd_vms_output_flush (abfd);
+ break;
+
+ case ALPHA_R_NOP:
+ udata
+ = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
+ etir_output_check (abfd, section, curr_addr,
+ 32 + 1 + strlen (udata->origname));
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STC_NOP_GBL, -1);
+ _bfd_vms_output_long (abfd, (unsigned long) udata->lkindex);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->address);
+ _bfd_vms_output_long (abfd, (unsigned long) 0x47ff041f);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->addend);
+ _bfd_vms_output_counted
+ (abfd, _bfd_vms_length_hash_symbol
+ (abfd, udata->origname, EOBJ_S_C_SYMSIZ));
+ _bfd_vms_output_flush (abfd);
+ break;
+
+ case ALPHA_R_BSR:
+ (*_bfd_error_handler) (_("Spurious ALPHA_R_BSR reloc"));
+ break;
+
+ case ALPHA_R_LDA:
+ udata
+ = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
+ etir_output_check (abfd, section, curr_addr,
+ 32 + 1 + strlen (udata->origname));
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STC_LDA_GBL, -1);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->lkindex + 1);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->address);
+ _bfd_vms_output_long (abfd, (unsigned long) 0x237B0000);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->bsym->section->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->addend);
+ _bfd_vms_output_counted
+ (abfd, _bfd_vms_length_hash_symbol
+ (abfd, udata->origname, EOBJ_S_C_SYMSIZ));
+ _bfd_vms_output_flush (abfd);
+ break;
+
+ case ALPHA_R_BOH:
+ udata
+ = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
+ etir_output_check (abfd, section, curr_addr,
+ 32 + 1 + strlen (udata->origname));
+ _bfd_vms_output_begin (abfd, ETIR_S_C_STC_BOH_GBL, -1);
+ _bfd_vms_output_long (abfd, (unsigned long) udata->lkindex);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->address);
+ _bfd_vms_output_long (abfd, (unsigned long) 0xD3400000);
+ _bfd_vms_output_long
+ (abfd, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (abfd, (uquad) rptr->addend);
+ _bfd_vms_output_counted
+ (abfd, _bfd_vms_length_hash_symbol
+ (abfd, udata->origname, EOBJ_S_C_SYMSIZ));
+ _bfd_vms_output_flush (abfd);
+ break;
+
+ default:
+ (*_bfd_error_handler) (_("Unhandled relocation %s"),
+ rptr->howto->name);
+ break;
}
- else
+
+ curr_data += size;
+ curr_addr += size;
+ } /* End of relocs loop. */
+
+ if (!pass2_in_progress)
+ {
+ /* Output rest of section. */
+ if (curr_addr > section->size)
+ (*_bfd_error_handler) (_("Size error in section %s"),
+ section->name);
+ size = section->size - curr_addr;
+ sto_imm (abfd, size, curr_data, curr_addr,
+ section->index, section->name);
+ curr_data += size;
+ curr_addr += size;
+
+ if (pass2_needed)
{
- /* No relocs, just dump. */
- sto_imm (abfd, sptr, vaddr, section->index);
- vaddr += sptr->size;
+ pass2_in_progress = 1;
+ goto new_pass;
}
-
- sptr = sptr->next;
}
-
- end_etir_record (abfd);
}
+
+ else /* (section->flags & SEC_RELOC) */
+ sto_imm (abfd, section->size, section->contents, 0,
+ section->index, section->name);
- section = section->next;
+ end_etir_record (abfd);
}
_bfd_vms_output_alignment (abfd, 2);
return 0;
}
-
-/* Write traceback data for bfd abfd. */
-
-int
-_bfd_vms_write_tbt (bfd * abfd ATTRIBUTE_UNUSED,
- int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "vms_write_tbt (%p, %d)\n", abfd, objtype);
-#endif
-
- return 0;
-}
-
-/* Write debug info for bfd abfd. */
-
-int
-_bfd_vms_write_dbg (bfd * abfd ATTRIBUTE_UNUSED,
- int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "vms_write_dbg (%p, objtype)\n", abfd, objtype);
-#endif
-
- return 0;
-}
/* vms.c -- BFD back-end for VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ Main file.
Written by Klaus K"ampf (kkaempf@rmi.de)
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"
#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
#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;
+\f
+#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;
-\f
-/* Initialize private data. */
+/* Initialize private data */
static bfd_boolean
vms_initialize (bfd * abfd)
{
- int i;
bfd_size_type amt;
bfd_set_start_address (abfd, (bfd_vma) -1);
amt = sizeof (struct vms_private_data_struct);
- abfd->tdata.any = bfd_alloc (abfd, amt);
+ abfd->tdata.any = bfd_zalloc (abfd, amt);
if (abfd->tdata.any == NULL)
return FALSE;
-#ifdef __ALPHA
- PRIV (is_vax) = FALSE;
-#else
- PRIV (is_vax) = TRUE;
-#endif
- PRIV (vms_buf) = NULL;
- PRIV (buf_size) = 0;
- PRIV (rec_length) = 0;
+ if (bfd_get_flavour (abfd) == bfd_target_ovax_flavour)
+ PRIV (is_vax) = TRUE;
+
PRIV (file_format) = FF_UNKNOWN;
- PRIV (fixup_done) = FALSE;
- PRIV (sections) = NULL;
amt = sizeof (struct stack_struct) * STACKSIZE;
PRIV (stack) = bfd_alloc (abfd, amt);
if (PRIV (stack) == NULL)
goto error_ret1;
- PRIV (stackptr) = 0;
amt = sizeof (struct bfd_hash_table);
PRIV (vms_symbol_table) = bfd_alloc (abfd, amt);
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;
return FALSE;
}
-/* Fill symbol->section with section ptr
+struct pair
+{
+ unsigned int section_count;
+ asection **sections;
+};
+
+/* Fill symbol->section with section pointer.
+
symbol->section is filled with the section index for defined symbols
- during reading the GSD/EGSD section. But we need the pointer to the
+ during reading the GSD/EGSD section. But we need the pointer to the
bfd section later.
- It has the correct value for referenced (undefined section) symbols
+ It has the correct value for referenced (undefined section) symbols.
- called from bfd_hash_traverse in vms_fixup_sections. */
+ Called from bfd_hash_traverse in vms_fixup_sections. */
static bfd_boolean
-fill_section_ptr (struct bfd_hash_entry * entry, void * sections)
+fill_section_ptr (struct bfd_hash_entry *entry, void *sections)
{
- asection *sec;
- asymbol *sym;
-
- sym = ((vms_symbol_entry *) entry)->symbol;
- sec = sym->section;
+ asymbol *sym = ((vms_symbol_entry *)entry)->symbol;
+ struct pair *data = (struct pair *)sections;
+ unsigned long sec = (unsigned long)sym->section;
#if VMS_DEBUG
vms_debug (6, "fill_section_ptr: sym %p, sec %p\n", sym, sec);
#endif
- /* Fill forward references (these contain section number, not section ptr). */
- if ((unsigned int) (size_t) sec < priv_section_count)
- sec = ((vms_symbol_entry *) entry)->symbol->section =
- ((asection **) sections)[(unsigned int) (size_t) sec];
-
- if (strcmp (sym->name, sec->name) == 0)
- sym->flags |= BSF_SECTION_SYM;
+ if (sec < data->section_count)
+ {
+ sym->section = data->sections[sec];
+ if (strcmp (sym->name, sym->section->name) == 0)
+ sym->flags |= BSF_SECTION_SYM;
+ }
+ else if (sec == (unsigned long)-1)
+ sym->section = &bfd_und_section;
+
return TRUE;
}
-/* Fixup sections
- set up all pointers and arrays, counters and sizes are fixed now
-
- we build a private sections vector for easy access since sections
- are always referenced by an index number.
-
- alloc PRIV(sections) according to abfd->section_count
- copy abfd->sections to PRIV(sections). */
-
+/* Fixup section pointers in symbols. */
static bfd_boolean
vms_fixup_sections (bfd * abfd)
{
+ struct pair data;
+
if (PRIV (fixup_done))
return TRUE;
- /* Traverse symbol table and fill in all section pointers. */
-
- /* Can't provide section count as argument to fill_section_ptr(). */
- priv_section_count = PRIV (section_count);
- bfd_hash_traverse (PRIV (vms_symbol_table), fill_section_ptr, (PRIV (sections)));
+ data.section_count = PRIV (section_count);
+ data.sections = PRIV (sections);
+ bfd_hash_traverse (PRIV (vms_symbol_table), fill_section_ptr, &data);
PRIV (fixup_done) = TRUE;
-
return TRUE;
}
-\f
-/* Check the format for a file being read.
- Return a (bfd_target *) if it's an object file or zero if not. */
-static const struct bfd_target *
-vms_object_p (bfd * abfd)
+/* Slurp an ordered set of VMS object records. */
+int
+_bfd_vms_slurp_object_records (bfd * abfd)
{
- int err = 0;
- int prev_type;
- const struct bfd_target *target_vector = NULL;
- const bfd_arch_info_type *arch = NULL;
- void * tdata_save = abfd->tdata.any;
- bfd_vma saddr_save = bfd_get_start_address (abfd);
-
-#if VMS_DEBUG
- vms_debug (1, "vms_object_p (%p)\n", abfd);
-#endif
-
- if (!vms_initialize (abfd))
- goto error_ret;
-
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
- goto err_wrong_format;
-
- prev_type = -1;
+ int err, new_type, type = -1;
do
{
#if VMS_DEBUG
vms_debug (7, "reading at %08lx\n", bfd_tell (abfd));
#endif
- if (_bfd_vms_next_record (abfd) < 0)
+ new_type = _bfd_vms_get_object_record (abfd);
+ if (new_type < 0)
{
#if VMS_DEBUG
vms_debug (2, "next_record failed\n");
#endif
- goto err_wrong_format;
+ return -1;
}
- if ((prev_type == EOBJ_S_C_EGSD)
- && (PRIV (rec_type) != EOBJ_S_C_EGSD))
+ if (type == EOBJ_S_C_EGSD && new_type != EOBJ_S_C_EGSD)
{
if (! vms_fixup_sections (abfd))
{
#if VMS_DEBUG
vms_debug (2, "vms_fixup_sections failed\n");
#endif
- goto err_wrong_format;
+ return -1;
}
}
- prev_type = PRIV (rec_type);
-
- if (target_vector == NULL)
- {
- if (prev_type <= OBJ_S_C_MAXRECTYP)
- target_vector = & vms_vax_vec;
- else
- target_vector = & vms_alpha_vec;
- }
+ type = new_type;
- switch (prev_type)
+ switch (type)
{
case OBJ_S_C_HDR:
case EOBJ_S_C_EMH:
- err = _bfd_vms_slurp_hdr (abfd, prev_type);
+ err = _bfd_vms_slurp_hdr (abfd, type);
break;
case OBJ_S_C_EOM:
case OBJ_S_C_EOMW:
case EOBJ_S_C_EEOM:
- err = _bfd_vms_slurp_eom (abfd, prev_type);
+ err = _bfd_vms_slurp_eom (abfd, type);
break;
case OBJ_S_C_GSD:
case EOBJ_S_C_EGSD:
- err = _bfd_vms_slurp_gsd (abfd, prev_type);
+ err = _bfd_vms_slurp_gsd (abfd, type);
break;
case OBJ_S_C_TIR:
case EOBJ_S_C_ETIR:
- err = _bfd_vms_slurp_tir (abfd, prev_type);
+ err = _bfd_vms_slurp_tir (abfd, type);
break;
case OBJ_S_C_DBG:
case EOBJ_S_C_EDBG:
- err = _bfd_vms_slurp_dbg (abfd, prev_type);
+ err = _bfd_vms_slurp_dbg (abfd, type);
+ PRIV (dst_ptr_end) = PRIV (image_ptr);
break;
case OBJ_S_C_TBT:
case EOBJ_S_C_ETBT:
- err = _bfd_vms_slurp_tbt (abfd, prev_type);
+ err = _bfd_vms_slurp_tbt (abfd, type);
+ PRIV (dst_ptr_end) = PRIV (image_ptr);
break;
case OBJ_S_C_LNK:
- err = _bfd_vms_slurp_lnk (abfd, prev_type);
+ err = _bfd_vms_slurp_lnk (abfd, type);
break;
default:
err = -1;
if (err != 0)
{
#if VMS_DEBUG
- vms_debug (2, "slurp type %d failed with %d\n", prev_type, err);
+ vms_debug (2, "slurp type %d failed with %d\n", type, err);
#endif
- goto err_wrong_format;
+ return err;
}
}
- while ((prev_type != EOBJ_S_C_EEOM) && (prev_type != OBJ_S_C_EOM) && (prev_type != OBJ_S_C_EOMW));
+ while (type != EOBJ_S_C_EEOM && type != OBJ_S_C_EOM && type != OBJ_S_C_EOMW);
+
+ return 0;
+}
+
+/* Slurp a VMS module and return an error status. */
+
+static int
+vms_slurp_module (bfd *abfd)
+{
+ int type, err;
+
+ if (PRIV (is_vax))
+ type = PRIV (vms_rec)[0];
+ else
+ type = bfd_getl16 (PRIV (vms_rec));
+
+ err = _bfd_vms_slurp_hdr (abfd, type);
+ if (err != 0)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return err;
+ }
+
+ return _bfd_vms_slurp_object_records (abfd);
+}
+
+/* Slurp a VMS image and return an error status. */
+
+static int
+vms_slurp_image (bfd *abfd)
+{
+ unsigned int isd_offset, ihs_offset;
+ int err;
+
+ err = _bfd_vms_slurp_ihd (abfd, &isd_offset, &ihs_offset);
+ if (err != 0)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return err;
+ }
- if (target_vector == & vms_vax_vec)
+ err = _bfd_vms_slurp_isd (abfd, isd_offset);
+ if (err != 0)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return err;
+ }
+
+ return _bfd_vms_slurp_ihs (abfd, ihs_offset);
+}
+
+/* Check the format for a file being read.
+ Return a (bfd_target *) if it's an object file or zero if not. */
+
+static const struct bfd_target *
+vms_object_p (bfd *abfd)
+{
+ const struct bfd_target *target_vector;
+ const bfd_arch_info_type *arch;
+ PTR tdata_save = abfd->tdata.any;
+ bfd_vma saddr_save = bfd_get_start_address (abfd);
+ int err = 0;
+
+#if VMS_DEBUG
+ vms_debug (1, "vms_object_p(%p)\n", abfd);
+#endif
+
+ if (!vms_initialize (abfd))
+ goto error_ret;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
+ goto err_wrong_format;
+
+ switch (_bfd_vms_get_first_record (abfd))
+ {
+ case FT_UNKNOWN:
+ default:
+ err = -1;
+ break;
+
+ case FT_MODULE:
+ err = vms_slurp_module (abfd);
+ break;
+
+ case FT_IMAGE:
+ err = vms_slurp_image (abfd);
+ break;
+ }
+
+ if (err != 0)
+ goto err_wrong_format;
+
+ if (PRIV (is_vax))
{
if (! vms_fixup_sections (abfd))
{
goto err_wrong_format;
}
- /* Set arch_info to vax. */
-
+ target_vector = &vms_vax_vec;
arch = bfd_scan_arch ("vax");
- PRIV (is_vax) = TRUE;
+
#if VMS_DEBUG
vms_debug (2, "arch is vax\n");
#endif
}
- else if (target_vector == & vms_alpha_vec)
+ else
{
/* Set arch_info to alpha. */
-
+ target_vector = &vms_alpha_vec;
arch = bfd_scan_arch ("alpha");
- PRIV (is_vax) = FALSE;
#if VMS_DEBUG
vms_debug (2, "arch is alpha\n");
#endif
}
- if (arch == NULL)
- {
-#if VMS_DEBUG
- vms_debug (2, "arch not found\n");
-#endif
- goto err_wrong_format;
- }
abfd->arch_info = arch;
-
return target_vector;
err_wrong_format:
bfd_set_error (bfd_error_wrong_format);
+
error_ret:
if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
bfd_release (abfd, abfd->tdata.any);
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
if (!vms_initialize (abfd))
return FALSE;
- {
-#ifdef __VAX
- const bfd_arch_info_type *arch = bfd_scan_arch ("vax");
-#else
- const bfd_arch_info_type *arch = bfd_scan_arch ("alpha");
-#endif
- if (arch == NULL)
- {
- bfd_set_error (bfd_error_wrong_format);
- return FALSE;
- }
- abfd->arch_info = arch;
- }
+ if (PRIV (is_vax))
+ arch = bfd_scan_arch ("vax");
+ else
+ arch = bfd_scan_arch ("alpha");
+
+ if (arch == 0)
+ {
+ bfd_set_error(bfd_error_wrong_format);
+ return FALSE;
+ }
+ abfd->arch_info = arch;
return TRUE;
}
/* 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
#if VMS_DEBUG
vms_debug (1, "vms_close_and_cleanup (%p)\n", abfd);
#endif
- if (abfd == NULL
- || abfd->tdata.any == NULL)
+ if (abfd == NULL || abfd->tdata.any == NULL)
return TRUE;
if (PRIV (vms_buf) != NULL)
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;
}
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;
vms_debug (1, "vms_new_section_hook (%p, [%d]%s), count %d\n",
abfd, section->index, section->name, section_count);
#endif
- bfd_set_section_alignment (abfd, section, 4);
+
+ bfd_set_section_alignment (abfd, section, 0);
if (section_count > PRIV (section_count))
{
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);
}
file_ptr offset ATTRIBUTE_UNUSED,
bfd_size_type buf_size ATTRIBUTE_UNUSED)
{
+ bfd_size_type size = section->size;
+
#if VMS_DEBUG
vms_debug (1, "vms_get_section_contents (%p, %s, %p, off %ld, size %d)\n",
abfd, section->name, buf, offset, (int)buf_size);
#endif
- /* Shouldn't be called, since all sections are IN_MEMORY. */
- return FALSE;
+ if (section->contents)
+ abort ();
+
+ section->contents = (unsigned char *) bfd_malloc (size);
+
+ if (section->contents == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
+
+ if (bfd_seek (abfd, section->filepos, SEEK_SET))
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return FALSE;
+ }
+
+ if (bfd_bread (section->contents, size, abfd) != size)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return FALSE;
+ }
+
+ section->flags |= SEC_IN_MEMORY;
+
+ if (buf)
+ memcpy (buf, section->contents + offset, (size_t) buf_size);
+
+ return TRUE;
}
/* Read the contents of a section.
#if VMS_DEBUG
vms_debug (1, "vms_truncate_arname (%p, %s, %s)\n", abfd, pathname, arhdr);
#endif
- return;
}
/* ??? write archive map. */
if (ret == NULL)
return;
- if (bfd_is_com_section (sec))
+ if (sec == 0)
+ ret->type = 'U';
+ else if (bfd_is_com_section (sec))
ret->type = 'C';
else if (bfd_is_abs_section (sec))
ret->type = 'A';
vms_debug (1, "vms_find_nearest_line (%p, %s, %p, %ld, <ret>, <ret>, <ret>)\n",
abfd, section->name, symbols, (long int)offset);
#endif
- return FALSE;
+ return _bfd_vms_find_nearest_dst_line (abfd, section, symbols, offset, file, func, line);
}
static bfd_boolean
/* Part 4.6, relocations. */
-/* Return the number of bytes required to store the relocation information
- associated with section sect attached to bfd abfd.
- If an error occurs, return -1. */
+/* Allocate the reloc buffer for the specified section. */
-static long
-vms_get_reloc_upper_bound (bfd * abfd ATTRIBUTE_UNUSED,
- asection *section ATTRIBUTE_UNUSED)
+static void
+alloc_reloc_stream (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
+ void *alloc_error)
{
+ unsigned char *ptr;
+
+ /* If there were no relocations, there is nothing to do. */
+ if (section->reloc_count == 0)
+ return;
+
+ ptr = bfd_malloc (vms_section_data (section)->reloc_size);
+ if (ptr == NULL)
+ {
+ *(bfd_boolean *)alloc_error = TRUE;
+ return;
+ }
+
+ vms_section_data (section)->reloc_stream = ptr;
+}
+
+/* Read in the relocs for the specified section and internalize them.
+
+ The implementation is loosely based on the SOM code and made up
+ of 3 distinct phases:
+
+ 1. When the VMS object is opened and parsed, the number and the size
+ of the relocations are computed for all sections. This makes it
+ possible to know upfront both which sections have no relocs and
+ the size of the reloc buffers for the other sections, at virtually
+ no cost for consumers that don't care about relocs at all.
+
+ 2. When vms_slurp_reloc_table is invoked for the first time on a section
+ with relocs, the object is traversed and all the reloc information
+ is saved in per-section reloc buffers. It would be very inefficient
+ to scan the whole file on each invocation, so we slurp for all the
+ sections at once.
+
+ 3. On subsequent invocations of vms_slurp_reloc_table, the relocs for the
+ specified section are fetched from the buffer, decoded and internalized.
+ The buffer is then freed since the internalized relocs are attached to
+ the section, turning additional invocations of vms_slurp_reloc_table
+ on the same section into no-ops.
+
+ Since VMS objects have very few sections, it could be profitable to merge
+ phase #2 and phase #3, i.e. to decode and internalize the relocs for all
+ the sections at once. The current implementation is more elegant. */
+
+static bfd_boolean
+vms_slurp_reloc_table (bfd *abfd, asection *section, asymbol **symbols)
+{
+ arelent *internal_relocs;
+ bfd_size_type amt;
+ int err;
+
+ /* If there were no relocations, there is nothing to do. */
+ if (section->reloc_count == 0)
+ return TRUE;
+
+ /* Return saved information about the relocations if it is available. */
+ if (section->relocation != NULL)
+ return TRUE;
+
+ /* If the relocation stream has not been slurped, do it now. */
+ if (vms_section_data (section)->reloc_stream == NULL)
+ {
+ bfd_boolean alloc_error = FALSE;
+ int type;
+
+ /* Size the reloc buffer for each section. */
+ bfd_map_over_sections (abfd, alloc_reloc_stream, &alloc_error);
+ if (alloc_error)
+ return FALSE;
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ return FALSE;
+
+ /* Reset section pointer. */
+ PRIV (image_section) = NULL;
+
+ do
+ {
+ type = _bfd_vms_get_object_record (abfd);
+ if (type != EOBJ_S_C_ETIR
+ && type != EOBJ_S_C_EDBG
+ && type != EOBJ_S_C_ETBT)
+ continue;
+ err = _bfd_vms_slurp_relocs (abfd);
+ if (err != 0)
+ {
+#if VMS_DEBUG
+ vms_debug (2, "slurp relocs failed with %d\n", err);
+#endif
+ return FALSE;
+ }
+ }
+ while (type != EOBJ_S_C_EEOM);
+ }
+
+ amt = section->reloc_count * sizeof (arelent);
+ internal_relocs = (arelent *) bfd_zalloc (abfd, amt);
+ if (internal_relocs == NULL)
+ return FALSE;
+
+ /* Decode and internalize the relocations. */
+ err = _bfd_vms_decode_relocs (abfd, internal_relocs, section, symbols);
+ if (err != 0)
+ {
#if VMS_DEBUG
- vms_debug (1, "vms_get_reloc_upper_bound (%p, %s)\n", abfd, section->name);
+ vms_debug (2, "decode relocs failed with %d\n", err);
#endif
- return -1L;
+ return FALSE;
+ }
+
+ /* We're done with the external relocations. Free them. */
+ free (vms_section_data (section)->reloc_stream);
+ vms_section_data (section)->reloc_stream = NULL;
+
+ /* Save our results and return success. */
+ section->relocation = internal_relocs;
+ return TRUE;
}
-/* Call the back end associated with the open BFD abfd and translate the
- external form of the relocation information attached to sec into the
- internal canonical form. Place the table into memory at loc, which has
- been preallocated, usually by a call to bfd_get_reloc_upper_bound.
- Returns the number of relocs, or -1 on error. */
+/* Return the number of bytes required to store the relocation
+ information associated with the given section. */
static long
-vms_canonicalize_reloc (bfd * abfd ATTRIBUTE_UNUSED,
- asection *section ATTRIBUTE_UNUSED,
- arelent **location ATTRIBUTE_UNUSED,
- asymbol **symbols ATTRIBUTE_UNUSED)
+vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
{
-#if VMS_DEBUG
- vms_debug (1, "vms_canonicalize_reloc (%p, %s, <ret>, <ret>)\n", abfd, section->name);
-#endif
- return FALSE;
+ return (section->reloc_count + 1) * sizeof (arelent *);
+}
+
+/* Convert relocations from VMS (external) form into BFD internal
+ form. Return the number of relocations. */
+
+static long
+vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr,
+ asymbol **symbols)
+{
+ arelent *tblptr;
+ int count;
+
+ if (! vms_slurp_reloc_table (abfd, section, symbols))
+ return -1;
+
+ count = section->reloc_count;
+ tblptr = section->relocation;
+
+ while (count--)
+ *relptr++ = tblptr++;
+
+ *relptr = (arelent *) NULL;
+ return section->reloc_count;
}
\f
/* This is just copied from ecoff-alpha, needs to be fixed probably. */
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
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;
#if VMS_DEBUG
vms_debug (1, "vms_set_arch_mach (%p, %d, %ld)\n", abfd, arch, mach);
#endif
- abfd->arch_info = bfd_scan_arch ("alpha");
- return TRUE;
+ if (arch != bfd_arch_alpha
+ && arch != bfd_arch_vax
+ && arch != bfd_arch_unknown)
+ return FALSE;
+
+ return bfd_default_set_arch_mach (abfd, arch, mach);
}
/* Sets the contents of the section section in BFD abfd to the data starting
- in memory at data. The data is written to the output section starting at
- offset offset for count bytes.
+ in memory at LOCATION. The data is written to the output section starting
+ at offset offset for count bytes.
Normally TRUE is returned, else FALSE. Possible error returns are:
o bfd_error_no_contents - The output section does not have the
abfd, section->name, location, (long int)offset, (int)count);
vms_debug (2, "size %d\n", (int) section->size);
#endif
- return _bfd_save_vms_section (abfd, section, location, offset, count);
+ if (count == (bfd_size_type)0)
+ return TRUE;
+
+ if (section->contents == NULL)
+ section->contents = bfd_alloc (abfd, section->size);
+ if (section->contents == NULL)
+ return FALSE;
+
+ memcpy (section->contents + offset, location, (size_t) count);
+ return TRUE;
}
/* Part 4.8, linker. */
#if VMS_DEBUG
vms_debug (1, "vms_get_dynamic_symtab_upper_bound (%p)\n", abfd);
#endif
- return 0;
+ return 0L;
}
static bfd_boolean
BFD_ENDIAN_LITTLE, /* Data byte order is little. */
BFD_ENDIAN_LITTLE, /* Header byte order is little. */
- (HAS_RELOC | HAS_SYMS
+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
| WP_TEXT | D_PAGED), /* Object flags. */
(SEC_ALLOC | SEC_LOAD | SEC_RELOC
| SEC_READONLY | SEC_CODE | SEC_DATA
| SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */
- 0, /* Symbol_leading_char. */
- ' ', /* AR_pad_char. */
- 15, /* AR_max_namelen. */
+ 0, /* symbol_leading_char. */
+ ' ', /* ar_pad_char. */
+ 15, /* ar_max_namelen. */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
NULL,
- NULL
+ (PTR) 0
};
const bfd_target vms_vax_vec =
(SEC_ALLOC | SEC_LOAD | SEC_RELOC
| SEC_READONLY | SEC_CODE | SEC_DATA
| SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */
- 0, /* Symbol_leading_char. */
- ' ', /* AR_pad_char. */
- 15, /* AR_max_namelen. */
+ 0, /* symbol_leading_char */
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Headers. */
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */
{_bfd_dummy_target, vms_object_p, /* bfd_check_format. */
vms_archive_p, _bfd_dummy_target},
NULL,
- NULL
+ (PTR) 0
};
/* vms.h -- Header file for VMS (Alpha and Vax) support.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
- Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
+ 2008, 2009 Free Software Foundation, Inc.
+
+ Main header file.
Written by Klaus K"ampf (kkaempf@rmi.de)
#ifndef VMS_H
#define VMS_H
-/* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object language) */
+/* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object
+ language). */
+
+#define VMS_BLOCK_SIZE 512
-/* VMS Text, information and relocation record (TIR/ETIR) definitions. */
+/* VMS Text Information and Relocation Records (TIR/ETIR). */
#define TIR_S_C_STA_GBL 0
#define TIR_S_C_STA_SB 1
#define ETIR_S_C_STA_GBL 0 /* Stack global symbol value. */
#define ETIR_S_C_STA_LW 1 /* Stack longword. */
#define ETIR_S_C_STA_QW 2 /* Stack quadword. */
-#define ETIR_S_C_STA_PQ 3 /* Stack psect base plus quadword offset. */
+#define ETIR_S_C_STA_PQ 3 /* Stack psect base + quadword off. */
#define ETIR_S_C_STA_LI 4 /* Stack literal. */
#define ETIR_S_C_STA_MOD 5 /* Stack module. */
#define ETIR_S_C_STA_CKARG 6 /* Check Arguments. */
#define ETIR_S_C_STC_NBH_PS 214 /* Store-conditional NOP,BSR or HINT at psect + offset. */
#define ETIR_S_C_MAXSTCCOD 214 /* Maximum store-conditional code. */
-/* VMS Global symbol definition record (GSD/EGSD). */
+#define ETIR_S_C_HEADER_SIZE 4 /* Size of the header of a command */
+
+/* VMS Global Symbol Directory Records (GSD/EGSD). */
#define GSD_S_K_ENTRIES 1
#define GSD_S_C_ENTRIES 1
#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
#define GPS_S_K_NAME 9
#define GPS_S_C_NAME 9
-#define EGPS_S_V_PIC 0x0001
-#define EGPS_S_V_LIB 0x0002
-#define EGPS_S_V_OVR 0x0004
-#define EGPS_S_V_REL 0x0008
-#define EGPS_S_V_GBL 0x0010
-#define EGPS_S_V_SHR 0x0020
-#define EGPS_S_V_EXE 0x0040
-#define EGPS_S_V_RD 0x0080
-#define EGPS_S_V_WRT 0x0100
-#define EGPS_S_V_VEC 0x0200
-#define EGPS_S_V_NOMOD 0x0400
-#define EGPS_S_V_COM 0x0800
-
+#define EGPS_S_B_ALIGN 4
+#define EGPS_S_W_FLAGS 6
+#define EGPS_S_L_ALLOC 8
+#define EGPS_S_B_NAMLNG 12
+
+#define EGPS_S_V_PIC 0x0001
+#define EGPS_S_V_LIB 0x0002
+#define EGPS_S_V_OVR 0x0004
+#define EGPS_S_V_REL 0x0008
+#define EGPS_S_V_GBL 0x0010
+#define EGPS_S_V_SHR 0x0020
+#define EGPS_S_V_EXE 0x0040
+#define EGPS_S_V_RD 0x0080
+#define EGPS_S_V_WRT 0x0100
+#define EGPS_S_V_VEC 0x0200
+#define EGPS_S_V_NOMOD 0x0400
+#define EGPS_S_V_COM 0x0800
+#define EGPS_S_V_ALLOC_64BIT 0x1000
+
+/* Symbol Defintion or Reference. */
#define GSY_S_M_WEAK 1
#define GSY_S_M_DEF 2
#define GSY_S_M_UNI 4
#define GSY_S_M_REL 8
-#define EGSY_S_V_WEAK 0x0001
-#define EGSY_S_V_DEF 0x0002
-#define EGSY_S_V_UNI 0x0004
-#define EGSY_S_V_REL 0x0008
-#define EGSY_S_V_COMM 0x0010
-#define EGSY_S_V_VECEP 0x0020
-#define EGSY_S_V_NORM 0x0040
+#define EGSY_S_W_FLAGS 6
+
+#define EGSY_S_V_WEAK 0x0001
+#define EGSY_S_V_DEF 0x0002
+#define EGSY_S_V_UNI 0x0004
+#define EGSY_S_V_REL 0x0008
+#define EGSY_S_V_COMM 0x0010
+#define EGSY_S_V_VECEP 0x0020
+#define EGSY_S_V_NORM 0x0040
+#define EGSY_S_V_QUAD_VAL 0x0080
#define LSY_S_M_DEF 2
#define LSY_S_M_REL 8
#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
#define DST_S_C_MODEND 189 /* End of module. */
#define DST_S_C_RTNBEG 190 /* Beginning of routine.*/
#define DST_S_C_RTNEND 191 /* End of routine. */
-#define DST_S_C_DELTA_PC_W 1 /* Incr PC. */
-#define DST_S_C_INCR_LINUM 2 /* Incr Line #. */
-#define DST_S_C_INCR_LINUM_W 3 /* Incr Line #. */
-#define DST_S_C_SET_LINUM_INCR 4
+
+/* These are used with DST_S_C_LINE_NUM. */
+#define DST_S_C_LINE_NUM_HEADER_SIZE 4
+
+#define DST_S_C_DELTA_PC_W 1 /* Incr PC. */
+#define DST_S_C_INCR_LINUM 2 /* Incr Line #. */
+#define DST_S_C_INCR_LINUM_W 3 /* Incr Line #. */
+#define DST_S_C_SET_LINUM_INCR 4
#define DST_S_C_SET_LINUM_INCR_W 5
#define DST_S_C_RESET_LINUM_INCR 6
-#define DST_S_C_BEG_STMT_MODE 7
-#define DST_S_C_END_STMT_MODE 8
-#define DST_S_C_SET_LINE_NUM 9 /* Set Line #. */
+#define DST_S_C_BEG_STMT_MODE 7
+#define DST_S_C_END_STMT_MODE 8
+#define DST_S_C_SET_LINE_NUM 9 /* Set Line #. */
#define DST_S_C_SET_PC 10
#define DST_S_C_SET_PC_W 11
#define DST_S_C_SET_PC_L 12
#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
#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
#define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */
#define DBG_S_C_STRUCT_START 0xab
#define DBG_S_C_STRUCT_END 0xac
-#define DST_K_TYPSPEC 0xaf /* Type specification. */
+#define DST_K_TYPSPEC 0xaf /* Type specification. */
/* These codes are used in the generation of the symbol definition records. */
#define DST_K_VFLAGS_NOVAL 0x80 /* Struct definition only. */
#define DST_K_VFLAGS_DSC 0xfa /* Descriptor used. */
#define DBG_S_C_VOID DST_K_TS_PTR
#define DBG_S_C_COMPLEX_ARRAY DST_K_TS_ARRAY
-/* VMS Module header record (EMH) definitions. */
+/* VMS Module Header Records (MHD/EMH). */
#define MHD_S_C_MHD 0
#define MHD_S_C_LNM 1
/* vms.c. */
extern asymbol *_bfd_vms_make_empty_symbol (bfd *);
+extern int _bfd_vms_slurp_object_records (bfd *abfd);
/* vms-gsd.c. */
-extern int _bfd_vms_slurp_gsd (bfd *, int);
-extern int _bfd_vms_write_gsd (bfd *, int);
+extern int _bfd_vms_slurp_gsd (bfd *abfd, int objtype);
+extern int _bfd_vms_write_gsd (bfd *abfd, int objtype);
+extern int _bfd_vms_slurp_dbg (bfd *abfd, int objtype);
+extern int _bfd_vms_write_dbg (bfd *abfd, int objtype);
+extern int _bfd_vms_slurp_tbt (bfd *abfd, int objtype);
+extern int _bfd_vms_write_tbt (bfd *abfd, int objtype);
-/* vms-mhd.c. */
+/* vms-misc.c. */
-extern int _bfd_vms_slurp_hdr (bfd *, int);
-extern int _bfd_vms_write_hdr (bfd *, int);
-extern int _bfd_vms_slurp_eom (bfd *, int);
-extern int _bfd_vms_write_eom (bfd *, int);
+extern int _bfd_vms_get_object_record (bfd *abfd);
+extern int _bfd_vms_get_first_record (bfd *abfd);
+
+/* vms-hdr.c. */
+
+extern int _bfd_vms_slurp_hdr (bfd *abfd, int objtype);
+extern int _bfd_vms_write_hdr (bfd *abfd, int objtype);
+extern int _bfd_vms_slurp_eom (bfd *abfd, int objtype);
+extern int _bfd_vms_write_eom (bfd *abfd, int objtype);
+extern bfd_boolean _bfd_vms_find_nearest_dst_line
+ (bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset,
+ const char **file, const char **func, unsigned int *line);
+extern int _bfd_vms_slurp_ihd
+ (bfd *abfd, unsigned int *isd_offset, unsigned int *ihs_offset);
+extern int _bfd_vms_slurp_isd (bfd *abfd, unsigned int offset);
+extern int _bfd_vms_slurp_ihs (bfd *abfd, unsigned int offset);
/* vms-tir.c. */
-extern int _bfd_vms_slurp_tir (bfd *, int);
-extern int _bfd_vms_slurp_dbg (bfd *, int);
-extern int _bfd_vms_slurp_tbt (bfd *, int);
-extern int _bfd_vms_slurp_lnk (bfd *, int);
-
-extern int _bfd_vms_write_tir (bfd *, int);
-extern int _bfd_vms_write_tbt (bfd *, int);
-extern int _bfd_vms_write_dbg (bfd *, int);
-
-/* The r_type field in a reloc is one of he following values. */
-#define ALPHA_R_IGNORE 0
-#define ALPHA_R_REFQUAD 1
-#define ALPHA_R_BRADDR 2
-#define ALPHA_R_HINT 3
-#define ALPHA_R_SREL16 4
-#define ALPHA_R_SREL32 5
-#define ALPHA_R_SREL64 6
-#define ALPHA_R_OP_PUSH 7
-#define ALPHA_R_OP_STORE 8
-#define ALPHA_R_OP_PSUB 9
-#define ALPHA_R_OP_PRSHIFT 10
-#define ALPHA_R_LINKAGE 11
-#define ALPHA_R_REFLONG 12
-#define ALPHA_R_CODEADDR 13
-
-/* Object language definitions. */
-
+extern int _bfd_vms_slurp_tir (bfd *abfd, int objtype);
+extern int _bfd_vms_write_tir (bfd *abfd, int objtype);
+extern int _bfd_vms_slurp_lnk (bfd *abfd, int objtype);
+
+extern int _bfd_vms_slurp_relocs (bfd *abfd);
+extern int _bfd_vms_decode_relocs
+ (bfd *abfd, arelent *relocs, asection *section, asymbol **symbols);
+
+/* The r_type field in a reloc is one of the following values. */
+#define ALPHA_R_IGNORE 0
+#define ALPHA_R_REFQUAD 1
+#define ALPHA_R_BRADDR 2
+#define ALPHA_R_HINT 3
+#define ALPHA_R_SREL16 4
+#define ALPHA_R_SREL32 5
+#define ALPHA_R_SREL64 6
+#define ALPHA_R_OP_PUSH 7
+#define ALPHA_R_OP_STORE 8
+#define ALPHA_R_OP_PSUB 9
+#define ALPHA_R_OP_PRSHIFT 10
+#define ALPHA_R_LINKAGE 11
+#define ALPHA_R_REFLONG 12
+#define ALPHA_R_CODEADDR 13
+#define ALPHA_R_NOP 14
+#define ALPHA_R_BSR 15
+#define ALPHA_R_LDA 16
+#define ALPHA_R_BOH 17
+
+/* VMS Object Language (OBJ/EOBJ). */
+
#define OBJ_S_C_HDR 0 /* VAX moule header record. */
#define OBJ_S_C_GSD 1 /* VAX glbal symbol definition record. */
#define OBJ_S_C_TIR 2 /* VAX tet information record. */
#define OBJ_S_C_LNK 6 /* VAX liker options record. */
#define OBJ_S_C_EOMW 7 /* VAX en of module word-psect record. */
#define OBJ_S_C_MAXRECTYP 7 /* VAX Lat assigned record type. */
+
#define EOBJ_S_C_EMH 8 /* EVAX mdule header record. */
#define EOBJ_S_C_EEOM 9 /* EVAX ed of module record. */
-#define EOBJ_S_C_EGSD 10 /* EVAX gobal symbol definition record.*/
-#define EOBJ_S_C_ETIR 11 /* EVAX txt information record. */
+#define EOBJ_S_C_EGSD 10 /* EVAX gobal symbol definition record. */
+#define EOBJ_S_C_ETIR 11 /* EVAX txt information record. */
#define EOBJ_S_C_EDBG 12 /* EVAX Dbugger information record. */
#define EOBJ_S_C_ETBT 13 /* EVAX Taceback information record. */
#define EOBJ_S_C_MAXRECTYP 13 /* EVAX Lst assigned record type. */
+
#define OBJ_S_K_SUBTYP 1
#define OBJ_S_C_SUBTYP 1
#define EOBJ_S_K_SUBTYP 4
#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__
#else
typedef unsigned long uquad;
#endif
-
-#define MAX_OUTREC_SIZE 4096
-#define MIN_OUTREC_LUFT 64
-
-typedef struct _vms_section
-{
- unsigned char *contents;
- bfd_vma offset;
- bfd_size_type size;
- struct _vms_section *next;
-} vms_section;
-
-extern vms_section * _bfd_get_vms_section (bfd *, int);
-
-typedef struct _vms_reloc
-{
- struct _vms_reloc *next;
- arelent *reloc;
- asection *section;
-} vms_reloc;
-
+
+#define MAX_OUTREC_SIZE 4096
+#define MIN_OUTREC_LUFT 64
+
/* VMS module header. */
-
-struct hdr_struc
-{
- int hdr_b_strlvl;
- long hdr_l_arch1;
- long hdr_l_arch2;
- long hdr_l_recsiz;
- char * hdr_t_name;
- char * hdr_t_version;
- char * hdr_t_date;
- char * hdr_c_lnm;
- char * hdr_c_src;
- char * hdr_c_ttl;
-};
-
-/* VMS end of module. */
-
-struct eom_struc
-{
- long eom_l_total_lps;
- unsigned char eom_b_comcod;
- bfd_boolean eom_has_transfer;
- unsigned char eom_b_tfrflg;
- long eom_l_psindx;
- long eom_l_tfradr;
-};
-
-enum file_format_enum { FF_UNKNOWN, FF_FOREIGN, FF_NATIVE, FF_VAX };
-
-typedef struct vms_symbol_struct
-{
- struct bfd_hash_entry bfd_hash;
- asymbol *symbol;
-} vms_symbol_entry;
-
+
+struct hdr_struct
+{
+ char hdr_b_strlvl;
+ int hdr_l_arch1;
+ int hdr_l_arch2;
+ int hdr_l_recsiz;
+ char *hdr_t_name;
+ char *hdr_t_version;
+ char *hdr_t_date;
+ char *hdr_c_lnm;
+ char *hdr_c_src;
+ char *hdr_c_ttl;
+ char *hdr_c_cpr;
+};
+
+#define EMH_S_W_HDRTYP 4
+#define EMH_S_B_STRLVL 6
+#define EMH_S_L_ARCH1 8
+#define EMH_S_L_ARCH2 12
+#define EH_S_L_RECSIZ 16
+#define EMH_S_B_NAMLNG 20
+
+#define EMH_DATE_LENGTH 17
+
+/* VMS End-Of-Module records (EOM/EEOM). */
+
+struct eom_struct
+{
+ int eom_l_total_lps;
+ short eom_w_comcod;
+ bfd_boolean eom_has_transfer;
+ char eom_b_tfrflg;
+ int eom_l_psindx;
+ int eom_l_tfradr;
+};
+
+#define EEOM_S_L_TOTAL_LPS 4
+#define EEOM_S_W_COMCOD 8
+#define EEOM_S_B_TFRFLG 10
+#define EEOM_S_L_PSINDX 12
+#define EEOM_S_L_TFRADR 16
+
+/* VMS Image Header Records (IHD/EIHD). */
+
+#define EIHD_S_K_MAJORID 3 /* Major id constant */
+#define EIHD_S_K_MINORID 0 /* Minor id constant */
+#define EIHD_S_K_EXE 1 /* Executable image */
+
+#define EIHD_S_L_SIZE 8
+#define EIHD_S_L_ISDOFF 12
+#define EIHD_S_L_SYMDBGOFF 20
+#define EIHD_S_Q_SYMVVA 40
+#define EIHD_S_L_IMGTYPE 52
+
+/* VMS Image Section Description Records (ISD/EISD). */
+
+#define EISD_S_L_EISDSIZE 8
+#define EISD_S_L_SECSIZE 12
+#define EISD_S_Q_VIR_ADDR 16
+#define EISD_S_L_FLAGS 24
+#define EISD_S_L_VBN 28
+#define EISD_S_R_CONTROL 32
+#define EISD_S_L_IDENT 36
+#define EISD_S_T_GBLNAM 40
+
+#define EISD_S_M_GBL 0x0001
+#define EISD_S_M_CRF 0x0002
+#define EISD_S_M_DZRO 0x0004
+#define EISD_S_M_WRT 0x0008
+#define EISD_S_M_INITALCODE 0x0010
+#define EISD_S_M_BASED 0x0020
+#define EISD_S_M_FIXUPVEC 0x0040
+#define EISD_S_M_RESIDENT 0x0080
+#define EISD_S_M_VECTOR 0x0100
+#define EISD_S_M_PROTECT 0x0200
+#define EISD_S_M_LASTCLU 0x0400
+#define EISD_S_M_EXE 0x0800
+#define EISD_S_M_NONSHRADR 0x1000
+#define EISD_S_M_QUAD_LENGTH 0x2000
+#define EISD_S_M_ALLOC_64BIT 0x4000
+
+/* VMS Image Header Symbol Records (IHS/EIHS). */
+
+#define EIHS_S_L_DSTVBN 8
+#define EIHS_S_L_DSTSIZE 12
+#define EIHS_S_L_GSTVBN 16
+#define EIHS_S_L_GSTSIZE 20
+#define EIHS_S_L_DMTVBN 24
+#define EIHS_S_L_DMTBYTES 28
+
+/* Debugger symbol definitions. */
+
+#define DBG_S_L_DMT_MODBEG 0
+#define DBG_S_L_DST_SIZE 4
+#define DBG_S_W_DMT_PSECT_COUNT 8
+#define DBG_S_C_DMT_HEADER_SIZE 12
+
+#define DBG_S_L_DMT_PSECT_START 0
+#define DBG_S_L_DMT_PSECT_LENGTH 4
+#define DBG_S_C_DMT_PSECT_SIZE 8
+
+
+enum file_format_enum { FF_UNKNOWN, FF_FOREIGN, FF_NATIVE };
+enum file_type_enum { FT_UNKNOWN, FT_MODULE, FT_IMAGE };
+
+typedef struct vms_symbol_struct
+{
+ struct bfd_hash_entry bfd_hash;
+ asymbol *symbol;
+} vms_symbol_entry;
+
/* Stack value for push/pop commands. */
-
-struct stack_struct
-{
- uquad value;
- int psect;
-};
-#define STACKSIZE 8192
-
-/* location stack definitions for CTL_DFLC, CTL_STLOC, and CTL_STKDL */
-
-struct location_struct
-{
- unsigned long value;
- int psect;
-};
-#define LOCATION_SAVE_SIZE 32
-
-#define VMS_SECTION_COUNT 1024
-
-struct vms_private_data_struct
-{
- bfd_boolean is_vax;
+
+struct stack_struct
+{
+ uquad value;
+ int psect;
+};
+
+#define STACKSIZE 8192
+
+/* A minimal decoding of DST compilation units. We only decode
+ what's needed to get to the line number information. */
+
+struct fileinfo
+{
+ char *name;
+ unsigned int srec;
+};
+
+struct srecinfo
+{
+ struct srecinfo *next;
+ unsigned int line;
+ unsigned int sfile;
+ unsigned int srec;
+};
+
+struct lineinfo
+{
+ struct lineinfo *next;
+ bfd_vma address;
+ unsigned int line;
+};
+
+struct funcinfo
+{
+ struct funcinfo *next;
+ char *name;
+ bfd_vma low;
+ bfd_vma high;
+};
+
+struct module
+{
+ /* Chain the previously read compilation unit. */
+ struct module *next;
+
+ /* The module name. */
+ char *name;
+
+ /* The start offset and size of debug info in the DST section. */
+ unsigned int modbeg;
+ unsigned int size;
+
+ /* The lowest and highest addresses contained in this compilation
+ unit as specified in the compilation unit header. */
+ bfd_vma low;
+ bfd_vma high;
+
+ /* The listing line table. */
+ struct lineinfo *line_table;
+
+ /* The source record table. */
+ struct srecinfo *srec_table;
+
+ /* A list of the functions found in this module. */
+ struct funcinfo *func_table;
+
+ /* Current allocation of file_table. */
+ unsigned int file_table_count;
+
+ /* An array of the files making up this module. */
+ struct fileinfo *file_table;
+};
+
+struct vms_private_data_struct
+{
+ bfd_boolean is_vax;
bfd_boolean fixup_done; /* Flag to indicate if all
section pointers and PRIV(sections)
are set up correctly. */
- unsigned char *vms_buf; /* Buffer to record. */
- int buf_size; /* Max size of buffer. */
- unsigned char *vms_rec; /* Actual record ptr. */
- int rec_length; /* Remaining record length. */
- int rec_size; /* Actual record size. */
- int rec_type; /* Actual record type. */
- enum file_format_enum file_format;
-
- struct hdr_struc hdr_data; /* Data from HDR/EMH record. */
- struct eom_struc eom_data; /* Data from EOM/EEOM record. */
- unsigned int section_count; /* # of sections in following array. */
- asection **sections; /* Array of GSD/EGSD sections. */
- int gsd_sym_count; /* # of GSD/EGSD symbols. */
- asymbol **symbols; /* Vector of GSD/EGSD symbols. */
- struct proc_value *procedure;
-
- struct stack_struct *stack;
- int stackptr;
-
- vms_section *vms_section_table[VMS_SECTION_COUNT];
-
+ unsigned char *vms_buf; /* record buffer */
+ unsigned int buf_size; /* size of record buffer */
+ unsigned char *vms_rec; /* record pointer in record buffer */
+ unsigned int rec_size; /* record size */
+ enum file_format_enum file_format;
+
+ struct hdr_struct hdr_data; /* data from HDR/EMH record */
+ struct eom_struct eom_data; /* data from EOM/EEOM record */
+ unsigned int section_count; /* # of sections in following array */
+ asection **sections; /* array of GSD/EGSD sections */
+ unsigned int gsd_sym_count; /* # of GSD/EGSD symbols */
+ asymbol **symbols; /* vector of GSD/EGSD symbols */
+ struct proc_value *procedure;
+
+ struct stack_struct *stack;
+ int stackptr;
+
struct bfd_hash_table *vms_symbol_table;
- struct bfd_symbol **symcache;
- int symnum;
-
- struct location_struct *location_stack;
-
- asection *image_section; /* Section for image_ptr. */
- unsigned char *image_ptr; /* A pointer to section->contents. */
-
- unsigned char pdsc[8]; /* Procedure descriptor. */
-
- /* Output routine storage. */
- unsigned char *output_buf; /* Output data. */
- int push_level;
- int pushed_size;
- int length_pos;
- int output_size;
- int output_alignment;
-
- /* Linkage index counter
- used by conditional store commands (TIR_S_C_STC_). */
- int vms_linkage_index;
-
- /* see tc-alpha.c of gas for a descripton. */
- int flag_hash_long_names; /* -+, hash instead of truncate. */
- int flag_show_after_trunc; /* -H, shw hashing/truncation. */
-};
-
-#define PRIV(name) ((struct vms_private_data_struct *) abfd->tdata.any)->name
-
+ struct bfd_symbol **symcache;
+ int symnum;
+
+ asection *image_section; /* section for image_ptr */
+ unsigned char *image_ptr; /* a pointer to section->contents */
+
+ unsigned char pdsc[8]; /* procedure descriptor */
+
+ struct module *modules; /* list of all compilation units */
+
+ struct dst_info *dst_info;
+ asection *dst_section;
+ unsigned char *dst_ptr_end;
+ unsigned int dst_ptr_offsets_count; /* # of offsets in following array */
+ unsigned int *dst_ptr_offsets; /* array of saved image_ptr offsets */
+
+ /* Shared library support */
+ bfd_vma symvva; /* relative virtual address of symbol vector */
+
+ /* Output routine storage */
+ unsigned char *output_buf; /* output data */
+ int push_level;
+ int pushed_size;
+ int length_pos;
+ int output_size;
+ int output_alignment;
+
+ /* linkage index counter used by conditional store commands */
+ int vms_linkage_index;
+
+ /* see tc-alpha.c of gas for a description. */
+ int flag_hash_long_names; /* -+, hash instead of truncate */
+ int flag_show_after_trunc; /* -H, show hashing/truncation */
+};
+
+#define PRIV(name) ((struct vms_private_data_struct *)abfd->tdata.any)->name
+
+/* Used to keep extra VMS specific information for a given section.
+
+ reloc_size holds the size of the relocation stream, note this
+ is very different from the number of relocations as VMS relocations
+ are variable length.
+
+ reloc_stream is the actual stream of relocation entries. */
+
+struct vms_section_data_struct
+{
+ bfd_size_type reloc_size;
+ unsigned char *reloc_stream;
+ bfd_size_type reloc_offset;
+ flagword vflags;
+};
+
+#define vms_section_data(sec) \
+ ((struct vms_section_data_struct *)sec->used_by_bfd)
+
+struct evax_private_udata_struct
+{
+ asymbol *bsym;
+ asymbol *enbsym;
+ char *origname;
+ int lkindex;
+};
+
#define SECTION_NAME_TEMPLATE "__SEC__%d"
#if VMS_DEBUG
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 *);
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 */