+2010-04-14 Tristan Gingold <gingold@adacore.com>
+
+ * Makefile.am (BFD32_BACKENDS): Remove vms-gsd.lo, vms-hdr.lo,
+ vms-tir.lo, vms.lo and add vms-alpha.lo
+ (BFD32_BACKENDS_CFILES): Remove vms-gsd.c, vms-hdr.c,
+ vms-tir.c, vms.c and add vms-alpha.c
+ * Makefile.in: Regenerate.
+ * configure.in (TDEFINES): Adjust file list for vms_alpha_vec.
+ Remove vms_vax_vec.
+ * configure: Regenerate.
+ * targets.c (vms_vax_vec): Remove the declaration.
+ (_bfd_target_vector): Remove vms_vax_vec.
+ * vms-alpha.c: New file.
+ * vms-gsd.c: Removed, rewritten in vms-alpha.c
+ * vms-hdr.c: Ditto.
+ * vms-tir.c: Ditto.
+ * vms.c: Ditto.
+ * vms-misc.c: Fix indentation and comments. Replace most of
+ #if VMS_DEBUG/vms_debug with vms_debug2.
+ (_bfd_vms_hash_newfunc): Moved to vms-alpha.c
+ (hash_string): Ditto.
+ (_bfd_vms_length_hash_symbol): Ditto.
+ (maybe_adjust_record_pointer_for_object): Ditto.
+ (_bfd_vms_get_object_record): Ditto.
+ (vms_get_remaining_object_record): Ditto.
+ (_bfd_vms_push): Ditto.
+ (_bfd_vms_pop): Ditto.
+ (_bfd_vms_get_header_values): Removed.
+ (_bfd_vms_get_first_record): Removed.
+ (vms_get_remaining_image_record): Removed.
+ (new_symbol): Removed.
+ (_bfd_vms_enter_symbol): Removed.
+ (_bfd_vms_save_sized_string): Use memcpy instead of strncpy.
+ (_bfd_vms_output_begin): Remove rechead parameter. Replace bfd
+ parameter with struct vms_rec_wr.
+ (_bfd_vms_output_push): Removed and replaced by ...
+ (_bfd_vms_output_begin_subrec): ... new function.
+ (_bfd_vms_output_alignment): Replace bfd parameter with
+ struct vms_rec_wr, and adjust.
+ (_bfd_vms_output_check): Ditto
+ (_bfd_vms_output_byte): Ditto.
+ (_bfd_vms_output_short): Ditto.
+ (_bfd_vms_output_long): Ditto.
+ (_bfd_vms_output_quad): Ditto.
+ (_bfd_vms_output_counted): Ditto.
+ (_bfd_vms_output_dump): Ditto.
+ (_bfd_vms_output_fill): Ditto.
+ (_bfd_vms_output_pop): Removed and replaced by ...
+ (_bfd_vms_output_end_subrec): ... new function.
+ (_bfd_vms_output_flush): Removed.
+ (_bfd_vms_output_align): New function.
+ (_bfd_vms_output_end): Add recwr parameter. Adjust for this new
+ parameter.
+ (vms_convert_to_var): New function imported from vms.c
+ (vms_convert_to_var_1): Ditto.
+ (vms_convert_to_var_unix_filename): Ditto.
+ (vms_get_module_name): Ditto.
+ (get_vms_time_string): Ditto.
+ (vms_time_to_time_t): Ditto.
+ (vms_rawtime_to_time_t): Ditto.
+ * vms.h: All macros for the VMS file format are now in include/vms.
+ Prototypes for vms.c, vms-gsd.c, vms-misc.c, vms-hdr.c, vms-tir.c
+ have been removed.
+ (struct vms_symbol_struct, struct stack_struct): Moved to vms-alpha.c
+ (struct fileinfo, struct srecinfo, struct lineinfo): Ditto.
+ (struct funcinfo, struct vms_private_data_struct): Ditto.
+ (struct vms_section_data_struct): Ditto.
+ (struct vms_rec_rd, stryct vms_rec_wr): New declarations.
+ (vms_get_module_name, get_vms_time_string): New declarations.
+ (vms_time_to_time_t, vms_rawtime_to_time_t): Ditto.
+ (_bfd_vms_output_begin_subrec, _bfd_vms_output_end_subrec): Ditto.
+ (_bfd_vms_save_sized_string, _bfd_vms_save_counted_string): Adjusted.
+ (_bfd_vms_output_begin, _bfd_vms_output_alignment): Ditto.
+ (_bfd_vms_output_end,_bfd_vms_output_check): Ditto.
+ (_bfd_vms_output_byte, _bfd_vms_output_short): Ditto.
+ (_bfd_vms_output_long, _bfd_vms_output_quad): Ditto.
+ (_bfd_vms_output_counted, _bfd_vms_output_dump): Ditto.
+ (_bfd_vms_output_fill): Ditto.
+ (bfd_vms_set_section_flags): Ditto.
+
2010-04-14 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* elflink.c (_bfd_elf_merge_symbol): Tighten up the test for early
vaxbsd.lo \
vaxnetbsd.lo \
versados.lo \
- vms-gsd.lo \
- vms-hdr.lo \
+ vms-alpha.lo \
vms-lib.lo \
vms-misc.lo \
- vms-tir.lo \
- vms.lo \
xcofflink.lo \
xsym.lo \
xtensa-isa.lo \
vaxbsd.c \
vaxnetbsd.c \
versados.c \
- vms-gsd.c \
- vms-hdr.c \
+ vms-alpha.c \
vms-lib.c \
vms-misc.c \
- vms-tir.c \
- vms.c \
xcofflink.c \
xsym.c \
xtensa-isa.c \
vaxbsd.lo \
vaxnetbsd.lo \
versados.lo \
- vms-gsd.lo \
- vms-hdr.lo \
- vms-lib.lo \
vms-misc.lo \
- vms-tir.lo \
- vms.lo \
+ vms-alpha.lo \
+ vms-lib.lo \
xcofflink.lo \
xsym.lo \
xtensa-isa.lo \
vaxbsd.c \
vaxnetbsd.c \
versados.c \
- vms-gsd.c \
- vms-hdr.c \
+ vms-alpha.c \
vms-lib.c \
vms-misc.c \
- vms-tir.c \
- vms.c \
xcofflink.c \
xsym.c \
xtensa-isa.c \
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vaxnetbsd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verilog.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/versados.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-gsd.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-hdr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-alpha.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-lib.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-misc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms-tir.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vms.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcofflink.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsym.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xtensa-isa.Plo@am__quote@
vax1knetbsd_vec) tb="$tb vax1knetbsd.lo aout32.lo" ;;
vaxbsd_vec) tb="$tb vaxbsd.lo aout32.lo" ;;
versados_vec) tb="$tb versados.lo" ;;
- vms_alpha_vec) tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo vms-lib.lo"; target_size=64 ;;
+ vms_alpha_vec) tb="$tb vms-alpha.lo vms-misc.lo vms-lib.lo"; target_size=64 ;;
vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;;
- vms_vax_vec) tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo" ;;
w65_vec) tb="$tb coff-w65.lo reloc16.lo" ;;
we32kcoff_vec) tb="$tb coff-we32k.lo" ;;
z80coff_vec) tb="$tb coff-z80.lo reloc16.lo" ;;
vax1knetbsd_vec) tb="$tb vax1knetbsd.lo aout32.lo" ;;
vaxbsd_vec) tb="$tb vaxbsd.lo aout32.lo" ;;
versados_vec) tb="$tb versados.lo" ;;
- vms_alpha_vec) tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo vms-lib.lo"; target_size=64 ;;
+ vms_alpha_vec) tb="$tb vms-alpha.lo vms-misc.lo vms-lib.lo"; target_size=64 ;;
vms_lib_txt_vec) tb="$tb vms-lib.lo vms-misc.lo" ;;
- vms_vax_vec) tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo" ;;
w65_vec) tb="$tb coff-w65.lo reloc16.lo" ;;
we32kcoff_vec) tb="$tb coff-we32k.lo" ;;
z80coff_vec) tb="$tb coff-z80.lo reloc16.lo" ;;
extern const bfd_target versados_vec;
extern const bfd_target vms_alpha_vec;
extern const bfd_target vms_lib_txt_vec;
-extern const bfd_target vms_vax_vec;
extern const bfd_target w65_vec;
extern const bfd_target we32kcoff_vec;
extern const bfd_target x86_64pe_vec;
&vms_alpha_vec,
#endif
&vms_lib_txt_vec,
- &vms_vax_vec,
&w65_vec,
&we32kcoff_vec,
&z80coff_vec,
--- /dev/null
+/* vms.c -- BFD back-end for EVAX (openVMS/Alpha) files.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Initial version written by Klaus Kaempf (kkaempf@rmi.de)
+ Major rewrite by Adacore.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* TODO:
+ o DMT
+ o PIC
+ o Generation of shared image
+ o Generation of GST in image
+ o Relocation optimizations
+ o EISD for the stack
+ o Vectors isect
+ o 64 bits sections
+ o Entry point
+ ...
+*/
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "bfdver.h"
+
+#include "vms.h"
+#include "vms/eihd.h"
+#include "vms/eiha.h"
+#include "vms/eihi.h"
+#include "vms/eihs.h"
+#include "vms/eisd.h"
+#include "vms/dmt.h"
+#include "vms/dst.h"
+#include "vms/eihvn.h"
+#include "vms/eobjrec.h"
+#include "vms/egsd.h"
+#include "vms/egps.h"
+#include "vms/eeom.h"
+#include "vms/emh.h"
+#include "vms/eiaf.h"
+#include "vms/shl.h"
+#include "vms/eicp.h"
+#include "vms/etir.h"
+#include "vms/egsy.h"
+#include "vms/esdf.h"
+#include "vms/esdfm.h"
+#include "vms/esdfv.h"
+#include "vms/esrf.h"
+#include "vms/egst.h"
+#include "vms/dsc.h"
+#include "vms/prt.h"
+#include "vms/internal.h"
+\f
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+/* 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
+/* These are used with DST_S_C_LINE_NUM. */
+#define DST_S_C_LINE_NUM_HEADER_SIZE 4
+
+/* These are used with DST_S_C_SOURCE */
+
+#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
+
+/* 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
+
+/* VMS module header. */
+
+struct hdr_struct
+{
+ char hdr_b_strlvl;
+ int hdr_l_arch1;
+ int hdr_l_arch2;
+ int hdr_l_recsiz;
+ char *hdr_t_name;
+ char *hdr_t_version;
+ char *hdr_t_date;
+ char *hdr_c_lnm;
+ char *hdr_c_src;
+ char *hdr_c_ttl;
+};
+
+#define EMH_DATE_LENGTH 17
+
+/* VMS End-Of-Module records (EOM/EEOM). */
+
+struct eom_struct
+{
+ unsigned int eom_l_total_lps;
+ unsigned short eom_w_comcod;
+ bfd_boolean eom_has_transfer;
+ unsigned char eom_b_tfrflg;
+ unsigned int eom_l_psindx;
+ unsigned int eom_l_tfradr;
+};
+
+struct vms_symbol_entry
+{
+ bfd *owner;
+
+ /* Common fields. */
+ unsigned char typ;
+ unsigned char data_type;
+ unsigned short flags;
+
+ /* Section and offset/value of the symbol. */
+ unsigned int section;
+ unsigned int value;
+
+ /* Section and offset/value for the entry point (only for subprg). */
+ unsigned int code_section;
+ unsigned int code_value;
+
+ /* Symbol vector offset. */
+ unsigned int symbol_vector;
+
+ /* Length of the name. */
+ unsigned char namelen;
+
+ char name[1];
+};
+
+/* Stack value for push/pop commands. */
+
+struct stack_struct
+{
+ bfd_vma value;
+ unsigned int reloc;
+};
+
+#define STACKSIZE 128
+
+/* 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;
+};
+
+/* BFD private data for alpha-vms. */
+
+struct vms_private_data_struct
+{
+ /* If true, relocs have been read. */
+ bfd_boolean reloc_done;
+
+ /* Record input buffer. */
+ struct vms_rec_rd recrd;
+ struct vms_rec_wr recwr;
+
+ 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 */
+
+ /* Array of raw symbols. */
+ struct vms_symbol_entry **syms;
+
+ /* Canonicalized symbols. */
+ asymbol **csymbols;
+
+ /* Number of symbols. */
+ unsigned int gsd_sym_count;
+ /* Size of the syms array. */
+ unsigned int max_sym_count;
+ /* Number of procedure symbols. */
+ unsigned int norm_sym_count;
+
+ /* Stack used to evaluate TIR/ETIR commands. */
+ struct stack_struct *stack;
+ int stackptr;
+
+ /* Content reading. */
+ asection *image_section; /* section for image_ptr */
+ file_ptr image_offset; /* Offset for image_ptr. */
+ bfd_boolean image_autoextend; /* Resize section if necessary. */
+
+ struct module *modules; /* list of all compilation units */
+
+ struct dst_info *dst_info;
+ asection *dst_section;
+
+ 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 */
+ unsigned int ident;
+ unsigned char matchctl;
+
+ /* Shared library index. This is used for input bfd while linking. */
+ unsigned int shr_index;
+
+ /* Used to place structures in the file. */
+ file_ptr file_pos;
+
+ /* Simply linked list of eisd. */
+ struct vms_internal_eisd_map *eisd_head;
+ struct vms_internal_eisd_map *eisd_tail;
+
+ /* Simply linked list of eisd for shared libraries. */
+ struct vms_internal_eisd_map *gbl_eisd_head;
+ struct vms_internal_eisd_map *gbl_eisd_tail;
+
+ /* 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 PRIV2(abfd, name) \
+ (((struct vms_private_data_struct *)(abfd)->tdata.any)->name)
+#define PRIV(name) PRIV2(abfd,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
+{
+ /* Maximnum number of entries in sec->relocation. */
+ unsigned reloc_max;
+
+ /* Corresponding eisd. Used only while generating executables. */
+ struct vms_internal_eisd_map *eisd;
+
+ /* PSC flags to be clear. */
+ flagword no_flags;
+
+ /* PSC flags to be set. */
+ flagword flags;
+};
+
+#define vms_section_data(sec) \
+ ((struct vms_section_data_struct *)sec->used_by_bfd)
+
+/* To be called from the debugger. */
+struct vms_private_data_struct *bfd_vms_get_data (bfd *abfd);
+
+static int vms_get_remaining_object_record (bfd *abfd, int read_so_far);
+static bfd_boolean _bfd_vms_slurp_object_records (bfd * abfd);
+static void alpha_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *);
+static void alpha_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *);
+static void alpha_vms_add_fixup_qr (struct bfd_link_info *, bfd *, bfd *,
+ bfd_vma);
+static void alpha_vms_add_lw_reloc (struct bfd_link_info *info);
+static void alpha_vms_add_qw_reloc (struct bfd_link_info *info);
+static void alpha_vms_add_lw_fixup (struct bfd_link_info *, unsigned int,
+ bfd_vma);
+
+struct vector_type
+{
+ unsigned int max_el;
+ unsigned int nbr_el;
+ void *els;
+};
+
+/* Number of elements in VEC. */
+
+#define VEC_COUNT(VEC) ((VEC).nbr_el)
+
+/* Get the address of the Nth element. */
+
+#define VEC_EL(VEC, TYPE, N) (((TYPE *)((VEC).els))[N])
+
+#define VEC_INIT(VEC) \
+ do { \
+ (VEC).max_el = 0; \
+ (VEC).nbr_el = 0; \
+ (VEC).els = NULL; \
+ } while (0)
+
+/* Be sure there is room for a new element. */
+
+static void vector_grow1 (struct vector_type *vec, size_t elsz);
+
+/* Allocate room for a new element and return its address. */
+
+#define VEC_APPEND(VEC, TYPE) \
+ (vector_grow1 (&VEC, sizeof (TYPE)), &VEC_EL(VEC, TYPE, (VEC).nbr_el++))
+
+/* Append an element. */
+
+#define VEC_APPEND_EL(VEC, TYPE, EL) \
+ (*(VEC_APPEND (VEC, TYPE)) = EL)
+
+struct alpha_vms_vma_ref
+{
+ bfd_vma vma; /* Vma in the output. */
+ bfd_vma ref; /* Reference in the input. */
+};
+
+struct alpha_vms_shlib_el
+{
+ bfd *abfd;
+ bfd_boolean has_fixups;
+
+ struct vector_type lp; /* Vector of bfd_vma. */
+ struct vector_type ca; /* Vector of bfd_vma. */
+ struct vector_type qr; /* Vector of struct alpha_vms_vma_ref. */
+};
+
+/* Alpha VMS linker hash table. */
+
+struct alpha_vms_link_hash_table
+{
+ struct bfd_link_hash_table root;
+
+ /* Vector of shared libaries. */
+ struct vector_type shrlibs;
+
+ /* Fixup section. */
+ asection *fixup;
+
+ /* Base address. Used by fixups. */
+ bfd_vma base_addr;
+};
+
+#define alpha_vms_link_hash(INFO) \
+ ((struct alpha_vms_link_hash_table *)(INFO->hash))
+
+/* Alpha VMS linker hash table entry. */
+
+struct alpha_vms_link_hash_entry
+{
+ struct bfd_link_hash_entry root;
+
+ /* Pointer to the original vms symbol. */
+ struct vms_symbol_entry *sym;
+};
+\f
+/* Image reading. */
+
+/* Read & process EIHD record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset,
+ unsigned int *eihs_offset)
+{
+ unsigned int imgtype, size;
+ bfd_vma symvva;
+ struct vms_eihd *eihd = (struct vms_eihd *)PRIV (recrd.rec);
+
+ vms_debug2 ((8, "_bfd_vms_slurp_eihd\n"));
+
+ size = bfd_getl32 (eihd->size);
+ imgtype = bfd_getl32 (eihd->imgtype);
+
+ if (imgtype == EIHD__K_EXE || imgtype == EIHD__K_LIM)
+ abfd->flags |= EXEC_P;
+
+ symvva = bfd_getl64 (eihd->symvva);
+ if (symvva != 0)
+ {
+ PRIV (symvva) = symvva;
+ abfd->flags |= DYNAMIC;
+ }
+
+ PRIV (ident) = bfd_getl32 (eihd->ident);
+ PRIV (matchctl) = eihd->matchctl;
+
+ *eisd_offset = bfd_getl32 (eihd->isdoff);
+ *eihs_offset = bfd_getl32 (eihd->symdbgoff);
+
+ vms_debug2 ((4, "EIHD size %d imgtype %d symvva 0x%lx eisd %d eihs %d\n",
+ size, imgtype, (unsigned long)symvva,
+ *eisd_offset, *eihs_offset));
+
+ return FALSE;
+}
+
+/* Read & process EISD record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
+{
+ int section_count = 0;
+
+ vms_debug2 ((8, "_bfd_vms_slurp_eisd\n"));
+
+ while (1)
+ {
+ struct vms_eisd *eisd;
+ unsigned int rec_size;
+ unsigned int size;
+ unsigned long long vaddr;
+ unsigned int flags;
+ unsigned int vbn;
+ char *name = NULL;
+ asection *section;
+ flagword bfd_flags;
+
+ eisd = (struct vms_eisd *)(PRIV (recrd.rec) + offset);
+ rec_size = bfd_getl32 (eisd->eisdsize);
+
+ if (rec_size == 0)
+ break;
+
+ /* Skip to next block if pad. */
+ if (rec_size == 0xffffffff)
+ {
+ offset = (offset + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
+ continue;
+ }
+ else
+ offset += rec_size;
+
+ size = bfd_getl32 (eisd->secsize);
+ vaddr = bfd_getl64 (eisd->virt_addr);
+ flags = bfd_getl32 (eisd->flags);
+ vbn = bfd_getl32 (eisd->vbn);
+
+ vms_debug2 ((4, "EISD at 0x%x size 0x%x addr 0x%lx flags 0x%x blk %d\n",
+ offset, size, (unsigned long)vaddr, flags, vbn));
+
+ /* 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__M_EXE)
+ bfd_flags |= SEC_CODE | SEC_HAS_CONTENTS | SEC_LOAD;
+
+ if (flags & EISD__M_NONSHRADR)
+ bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
+
+ if (!(flags & EISD__M_WRT))
+ bfd_flags |= SEC_READONLY;
+
+ if (flags & EISD__M_DZRO)
+ bfd_flags |= SEC_DATA;
+
+ if (flags & EISD__M_FIXUPVEC)
+ bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
+
+ if (flags & EISD__M_CRF)
+ bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD;
+
+ if (flags & EISD__M_GBL)
+ {
+ name = _bfd_vms_save_counted_string (eisd->gblnam);
+ bfd_flags |= SEC_COFF_SHARED_LIBRARY;
+ bfd_flags &= ~(SEC_ALLOC | SEC_LOAD);
+ }
+ else if (flags & EISD__M_FIXUPVEC)
+ name = "$FIXUPVEC$";
+ else if (eisd->type == EISD__K_USRSTACK)
+ name = "$STACK$";
+ else
+ {
+ const char *pfx;
+
+ name = (char*) bfd_alloc (abfd, 32);
+ if (flags & EISD__M_DZRO)
+ pfx = "BSS";
+ else if (flags & EISD__M_EXE)
+ pfx = "CODE";
+ else if (!(flags & EISD__M_WRT))
+ pfx = "RO";
+ else
+ pfx = "LOCAL";
+ BFD_ASSERT (section_count < 999);
+ sprintf (name, "$%s_%03d$", pfx, section_count++);
+ }
+
+ section = bfd_make_section (abfd, name);
+
+ if (!section)
+ return FALSE;
+
+ section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : 0;
+ section->size = size;
+ section->vma = vaddr;
+
+ if (!bfd_set_section_flags (abfd, section, bfd_flags))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Read & process EIHS record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset)
+{
+ unsigned char *p = PRIV (recrd.rec) + offset;
+ unsigned int gstvbn = bfd_getl32 (p + EIHS__L_GSTVBN);
+ unsigned int gstsize ATTRIBUTE_UNUSED = bfd_getl32 (p + EIHS__L_GSTSIZE);
+ unsigned int dstvbn = bfd_getl32 (p + EIHS__L_DSTVBN);
+ unsigned int dstsize = bfd_getl32 (p + EIHS__L_DSTSIZE);
+ unsigned int dmtvbn = bfd_getl32 (p + EIHS__L_DMTVBN);
+ unsigned int dmtbytes = bfd_getl32 (p + EIHS__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 FALSE;
+
+ section->size = dstsize;
+ section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1);
+
+ if (!bfd_set_section_flags (abfd, section, bfd_flags))
+ return FALSE;
+
+ 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 FALSE;
+
+ section->size = dmtbytes;
+ section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1);
+
+ if (!bfd_set_section_flags (abfd, section, bfd_flags))
+ return FALSE;
+ }
+
+ if (gstvbn)
+ {
+ flagword bfd_flags = SEC_HAS_CONTENTS;
+
+ section = bfd_make_section (abfd, "$GST$");
+ if (!section)
+ return FALSE;
+
+ if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET))
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return FALSE;
+ }
+
+ if (_bfd_vms_slurp_object_records (abfd) != TRUE)
+ return FALSE;
+
+ section->filepos = VMS_BLOCK_SIZE * (gstvbn - 1);
+ section->size = bfd_tell (abfd) - section->filepos;
+
+ if (!bfd_set_section_flags (abfd, section, bfd_flags))
+ return FALSE;
+
+ abfd->flags |= HAS_SYMS;
+ }
+
+ return TRUE;
+}
+\f
+/* Object file reading. */
+
+/* Object file input functions. */
+
+/* Get next record from object file to vms_buf.
+ Set PRIV(buf_size) and return it
+
+ This is a little tricky since it should be portable.
+
+ The openVMS object file has 'variable length' which means that
+ read() returns data in chunks of (hopefully) correct and expected
+ size. The linker (and other tools on VMS) depend on that. Unix
+ doesn't know about 'formatted' files, so reading and writing such
+ an object file in a Unix environment is not trivial.
+
+ With the tool 'file' (available on all VMS FTP sites), one
+ can view and change the attributes of a file. Changing from
+ 'variable length' to 'fixed length, 512 bytes' reveals the
+ record size at the first 2 bytes of every record. The same
+ may happen during the transfer of object files from VMS to Unix,
+ at least with UCX, the DEC implementation of TCP/IP.
+
+ The VMS format repeats the size at bytes 2 & 3 of every record.
+
+ On the first call (file_format == FF_UNKNOWN) we check if
+ the first and the third byte pair (!) of the record match.
+ If they do it's an object file in an Unix environment or with
+ wrong attributes (FF_FOREIGN), else we should be in a VMS
+ environment where read() returns the record size (FF_NATIVE).
+
+ Reading is always done in 2 steps:
+ 1. first just the record header is read and the size extracted,
+ 2. then the read buffer is adjusted and the remaining bytes are
+ read in.
+
+ All file I/O is done on even file positions. */
+
+#define VMS_OBJECT_ADJUSTMENT 2
+
+static void
+maybe_adjust_record_pointer_for_object (bfd *abfd)
+{
+ /* Set the file format once for all on the first invocation. */
+ if (PRIV (recrd.file_format) == FF_UNKNOWN)
+ {
+ if (PRIV (recrd.rec)[0] == PRIV (recrd.rec)[4]
+ && PRIV (recrd.rec)[1] == PRIV (recrd.rec)[5])
+ PRIV (recrd.file_format) = FF_FOREIGN;
+ else
+ PRIV (recrd.file_format) = FF_NATIVE;
+ }
+
+ /* The adjustment is needed only in an Unix environment. */
+ if (PRIV (recrd.file_format) == FF_FOREIGN)
+ PRIV (recrd.rec) += VMS_OBJECT_ADJUSTMENT;
+}
+
+/* Implement step #1 of the object record reading procedure.
+ Return the record type or -1 on failure. */
+
+static int
+_bfd_vms_get_object_record (bfd *abfd)
+{
+ unsigned int test_len;
+ int type;
+ int off = 0;
+
+ vms_debug2 ((8, "_bfd_vms_get_obj_record\n"));
+
+ test_len = 6;
+
+ /* Skip odd alignment byte. */
+ if (bfd_tell (abfd) & 1)
+ {
+ if (bfd_bread (PRIV (recrd.buf), 1, abfd) != 1)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ /* Alignment byte may be present or not. This is not easy to
+ detect but all object record types are not 0 (on Alpha VMS).
+ We also hope that pad byte is 0. */
+ if (PRIV (recrd.buf)[0])
+ off = 1;
+ }
+
+ /* Read the record header */
+ if (bfd_bread (PRIV (recrd.buf) + off, test_len - off, abfd)
+ != test_len - off)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+
+ /* Reset the record pointer. */
+ PRIV (recrd.rec) = PRIV (recrd.buf);
+ maybe_adjust_record_pointer_for_object (abfd);
+
+ if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+ return -1;
+
+ type = bfd_getl16 (PRIV (recrd.rec));
+
+ vms_debug2 ((8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
+ PRIV (recrd.rec), PRIV (recrd.rec_size), type));
+
+ 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)
+{
+ unsigned int to_read;
+
+ vms_debug2 ((8, "vms_get_remaining_obj_record\n"));
+
+ /* Extract record size. */
+ PRIV (recrd.rec_size) = bfd_getl16 (PRIV (recrd.rec) + 2);
+
+ if (PRIV (recrd.rec_size) <= 0)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return 0;
+ }
+
+ /* That's what the linker manual says. */
+ if (PRIV (recrd.rec_size) > EOBJ__C_MAXRECSIZ)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return 0;
+ }
+
+ /* Take into account object adjustment. */
+ to_read = PRIV (recrd.rec_size);
+ if (PRIV (recrd.file_format) == FF_FOREIGN)
+ to_read += VMS_OBJECT_ADJUSTMENT;
+
+ /* Adjust the buffer. */
+ if (to_read > PRIV (recrd.buf_size))
+ {
+ PRIV (recrd.buf)
+ = (unsigned char *) bfd_realloc (PRIV (recrd.buf), to_read);
+ if (PRIV (recrd.buf) == NULL)
+ return 0;
+ PRIV (recrd.buf_size) = to_read;
+ }
+
+ /* Read the remaining record. */
+ to_read -= read_so_far;
+
+ vms_debug2 ((8, "vms_get_remaining_obj_record: to_read %d\n", to_read));
+
+ if (bfd_bread (PRIV (recrd.buf) + read_so_far, to_read, abfd) != to_read)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return 0;
+ }
+
+ /* Reset the record pointer. */
+ PRIV (recrd.rec) = PRIV (recrd.buf);
+ maybe_adjust_record_pointer_for_object (abfd);
+
+ vms_debug2 ((8, "vms_get_remaining_obj_record: size %d\n",
+ PRIV (recrd.rec_size)));
+
+ return PRIV (recrd.rec_size);
+}
+
+/* Read and process emh record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_ehdr (bfd *abfd)
+{
+ unsigned char *ptr;
+ unsigned char *vms_rec;
+ int subtype;
+
+ vms_rec = PRIV (recrd.rec);
+
+ vms_debug2 ((2, "HDR/EMH\n"));
+
+ subtype = bfd_getl16 (vms_rec + 4);
+
+ vms_debug2 ((3, "subtype %d\n", subtype));
+
+ switch (subtype)
+ {
+ case EMH__C_MHD:
+ /* Module header. */
+ PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
+ PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
+ PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
+ PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
+ PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20);
+ ptr = vms_rec + 20 + vms_rec[20] + 1;
+ PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
+ ptr += *ptr + 1;
+ PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
+ break;
+
+ case EMH__C_LNM:
+ PRIV (hdr_data).hdr_c_lnm =
+ _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
+ break;
+
+ case EMH__C_SRC:
+ PRIV (hdr_data).hdr_c_src =
+ _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
+ break;
+
+ case EMH__C_TTL:
+ PRIV (hdr_data).hdr_c_ttl =
+ _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
+ break;
+
+ case EMH__C_CPR:
+ case EMH__C_MTC:
+ case EMH__C_GTX:
+ break;
+
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Typical sections for evax object files. */
+
+#define EVAX_ABS_NAME "$ABS$"
+#define EVAX_CODE_NAME "$CODE$"
+#define EVAX_LINK_NAME "$LINK$"
+#define EVAX_DATA_NAME "$DATA$"
+#define EVAX_BSS_NAME "$BSS$"
+#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$"
+#define EVAX_READONLY_NAME "$READONLY$"
+#define EVAX_LITERAL_NAME "$LITERAL$"
+#define EVAX_LITERALS_NAME "$LITERALS"
+#define EVAX_COMMON_NAME "$COMMON$"
+#define EVAX_LOCAL_NAME "$LOCAL$"
+
+struct sec_flags_struct
+{
+ const char *name; /* Name of section. */
+ int vflags_always;
+ flagword flags_always; /* Flags we set always. */
+ int vflags_hassize;
+ flagword flags_hassize; /* Flags we set if the section has a size > 0. */
+};
+
+/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible. */
+
+static struct sec_flags_struct evax_section_flags[] =
+ {
+ { EVAX_ABS_NAME,
+ (EGPS__V_SHR),
+ (SEC_DATA),
+ (EGPS__V_SHR),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
+ { EVAX_CODE_NAME,
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE),
+ (SEC_CODE),
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE),
+ (SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
+ { EVAX_LITERAL_NAME,
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD),
+ (SEC_DATA | SEC_READONLY),
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+ { EVAX_LINK_NAME,
+ (EGPS__V_REL | EGPS__V_RD),
+ (SEC_DATA | SEC_READONLY),
+ (EGPS__V_REL | EGPS__V_RD),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+ { EVAX_DATA_NAME,
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD),
+ (SEC_DATA),
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
+ { EVAX_BSS_NAME,
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD),
+ (SEC_NO_FLAGS),
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD),
+ (SEC_ALLOC) },
+ { EVAX_READONLYADDR_NAME,
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD),
+ (SEC_DATA | SEC_READONLY),
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+ { EVAX_READONLY_NAME,
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD),
+ (SEC_DATA | SEC_READONLY),
+ (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+ { EVAX_LOCAL_NAME,
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
+ (SEC_DATA),
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
+ { EVAX_LITERALS_NAME,
+ (EGPS__V_PIC | EGPS__V_OVR),
+ (SEC_DATA | SEC_READONLY),
+ (EGPS__V_PIC | EGPS__V_OVR),
+ (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+ { NULL,
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
+ (SEC_DATA),
+ (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
+ (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
+ };
+
+/* Retrieve bfd section flags by name and size. */
+
+static flagword
+vms_secflag_by_name (bfd *abfd ATTRIBUTE_UNUSED,
+ struct sec_flags_struct *section_flags,
+ char *name,
+ int hassize)
+{
+ int i = 0;
+
+ while (section_flags[i].name != NULL)
+ {
+ if (strcmp (name, section_flags[i].name) == 0)
+ {
+ if (hassize)
+ return section_flags[i].flags_hassize;
+ else
+ return section_flags[i].flags_always;
+ }
+ i++;
+ }
+ if (hassize)
+ return section_flags[i].flags_hassize;
+ return section_flags[i].flags_always;
+}
+
+/* Retrieve vms section flags by name and size. */
+
+static flagword
+vms_esecflag_by_name (struct sec_flags_struct *section_flags,
+ char *name,
+ int hassize)
+{
+ int i = 0;
+
+ while (section_flags[i].name != NULL)
+ {
+ if (strcmp (name, section_flags[i].name) == 0)
+ {
+ if (hassize)
+ return section_flags[i].vflags_hassize;
+ else
+ return section_flags[i].vflags_always;
+ }
+ i++;
+ }
+ if (hassize)
+ return section_flags[i].vflags_hassize;
+ return section_flags[i].vflags_always;
+}
+
+/* Input routines. */
+
+static struct vms_symbol_entry *
+add_symbol (bfd *abfd, const unsigned char *ascic)
+{
+ struct vms_symbol_entry *entry;
+ int len;
+
+ len = *ascic++;
+ entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len);
+ if (entry == NULL)
+ return NULL;
+ entry->namelen = len;
+ memcpy (entry->name, ascic, len);
+ entry->name[len] = 0;
+ entry->owner = abfd;
+
+ if (PRIV (gsd_sym_count) >= PRIV (max_sym_count))
+ {
+ if (PRIV (max_sym_count) == 0)
+ {
+ PRIV (max_sym_count) = 128;
+ PRIV (syms) = bfd_malloc
+ (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *));
+ }
+ else
+ {
+ PRIV (max_sym_count) *= 2;
+ PRIV (syms) = bfd_realloc
+ (PRIV (syms),
+ (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *)));
+ }
+ if (PRIV (syms) == NULL)
+ return NULL;
+ }
+
+ PRIV (syms)[PRIV (gsd_sym_count)++] = entry;
+ return entry;
+}
+
+/* Read and process EGSD. Return FALSE on failure. */
+
+static bfd_boolean
+_bfd_vms_slurp_egsd (bfd * abfd)
+{
+ int gsd_type, gsd_size;
+ asection *section;
+ unsigned char *vms_rec;
+ flagword new_flags, old_flags;
+ char *name;
+ unsigned long base_addr;
+ unsigned long align_addr;
+
+ vms_debug2 ((2, "EGSD\n"));
+
+ PRIV (recrd.rec) += 8; /* Skip type, size, align pad. */
+ PRIV (recrd.rec_size) -= 8;
+
+ /* Calculate base address for each section. */
+ base_addr = 0L;
+
+ while (PRIV (recrd.rec_size) > 0)
+ {
+ vms_rec = PRIV (recrd.rec);
+
+ gsd_type = bfd_getl16 (vms_rec);
+ gsd_size = bfd_getl16 (vms_rec + 2);
+
+ vms_debug2 ((3, "egsd_type %d\n", gsd_type));
+
+ switch (gsd_type)
+ {
+ case EGSD__C_PSC:
+ {
+ /* Program section definition. */
+ struct vms_egps *egps = (struct vms_egps *)vms_rec;
+ name = _bfd_vms_save_counted_string (&egps->namlng);
+ section = bfd_make_section (abfd, name);
+ if (!section)
+ return FALSE;
+ old_flags = bfd_getl16 (egps->flags);
+ vms_section_data (section)->flags = old_flags;
+ vms_section_data (section)->no_flags = 0;
+ section->size = bfd_getl32 (egps->alloc);
+ new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
+ section->size > 0);
+ if (!(old_flags & EGPS__V_NOMOD))
+ {
+ new_flags |= SEC_HAS_CONTENTS;
+ if (old_flags & EGPS__V_REL)
+ new_flags |= SEC_RELOC;
+ }
+ if (!bfd_set_section_flags (abfd, section, new_flags))
+ return FALSE;
+ section->alignment_power = egps->align;
+ align_addr = (1 << section->alignment_power);
+ if ((base_addr % align_addr) != 0)
+ base_addr += (align_addr - (base_addr % align_addr));
+ section->vma = (bfd_vma)base_addr;
+ base_addr += section->size;
+ section->filepos = (unsigned int)-1;
+#if VMS_DEBUG
+ vms_debug (4, "EGSD P-section %d (%s, flags %04x) ",
+ section->index, name, old_flags);
+ vms_debug (4, "%lu bytes at 0x%08lx (mem %p)\n",
+ (unsigned long)section->size,
+ (unsigned long)section->vma, section->contents);
+#endif
+ }
+ break;
+
+ case EGSD__C_SYM:
+ {
+ int nameoff;
+ struct vms_symbol_entry *entry;
+ struct vms_egsy *egsy = (struct vms_egsy *) vms_rec;
+
+ old_flags = bfd_getl16 (egsy->flags);
+ if (old_flags & EGSY__V_DEF)
+ nameoff = ESDF__B_NAMLNG;
+ else
+ nameoff = ESRF__B_NAMLNG;
+
+ entry = add_symbol (abfd, vms_rec + nameoff);
+ if (entry == NULL)
+ return FALSE;
+
+ /* Allow only duplicate reference. */
+ if ((entry->flags & EGSY__V_DEF) && (old_flags & EGSY__V_DEF))
+ abort ();
+
+ if (entry->typ == 0)
+ {
+ entry->typ = gsd_type;
+ entry->data_type = egsy->datyp;
+ entry->flags = old_flags;
+ }
+
+ if (old_flags & EGSY__V_DEF)
+ {
+ struct vms_esdf *esdf = (struct vms_esdf *)vms_rec;
+
+ entry->value = bfd_getl64 (esdf->value);
+ entry->section = bfd_getl32 (esdf->psindx);
+
+ if (old_flags & EGSY__V_NORM)
+ {
+ PRIV (norm_sym_count)++;
+
+ entry->code_value = bfd_getl64 (esdf->code_address);
+ entry->code_section = bfd_getl32 (esdf->ca_psindx);
+ }
+ }
+ }
+ break;
+
+ case EGSD__C_SYMG:
+ {
+ int nameoff;
+ struct vms_symbol_entry *entry;
+ struct vms_egst *egst = (struct vms_egst *)vms_rec;
+
+ old_flags = bfd_getl16 (egst->header.flags);
+ if (old_flags & EGSY__V_DEF)
+ nameoff = ESDF__B_NAMLNG;
+ else
+ nameoff = ESRF__B_NAMLNG;
+
+ entry = add_symbol (abfd, &egst->namlng);
+
+ if (entry == NULL)
+ return FALSE;
+
+ entry->typ = gsd_type;
+ entry->data_type = egst->header.datyp;
+ entry->flags = old_flags;
+
+ entry->symbol_vector = bfd_getl32 (egst->value);
+
+ entry->section = bfd_getl32 (egst->psindx);
+ entry->value = bfd_getl64 (egst->lp_2);
+
+ if (old_flags & EGSY__V_NORM)
+ {
+ PRIV (norm_sym_count)++;
+
+ entry->code_value = bfd_getl64 (egst->lp_1);
+ entry->code_section = 0;
+ }
+ }
+ break;
+
+ case EGSD__C_IDC:
+ case EGSD__C_SYMM:
+ case EGSD__C_SYMV:
+ default:
+ (*_bfd_error_handler) (_("Unknown EGSD subtype %d"), gsd_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ PRIV (recrd.rec_size) -= gsd_size;
+ PRIV (recrd.rec) += gsd_size;
+ }
+
+ if (PRIV (gsd_sym_count) > 0)
+ abfd->flags |= HAS_SYMS;
+
+ return TRUE;
+}
+
+/* Stack routines for vms ETIR commands. */
+
+/* Push value and section index. */
+
+static void
+_bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc)
+{
+ vms_debug2 ((4, "<push %08lx (0x%08x) at %d>\n",
+ (unsigned long)val, reloc, PRIV (stackptr)));
+
+ PRIV (stack[PRIV (stackptr)]).value = val;
+ PRIV (stack[PRIV (stackptr)]).reloc = reloc;
+ PRIV (stackptr)++;
+ if (PRIV (stackptr) >= STACKSIZE)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
+ exit (1);
+ }
+}
+
+/* Pop value and section index. */
+
+static void
+_bfd_vms_pop (bfd *abfd, bfd_vma *val, unsigned int *rel)
+{
+ if (PRIV (stackptr) == 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
+ exit (1);
+ }
+ PRIV (stackptr)--;
+ *val = PRIV (stack[PRIV (stackptr)]).value;
+ *rel = PRIV (stack[PRIV (stackptr)]).reloc;
+
+ vms_debug2 ((4, "<pop %08lx (0x%08x)>\n", (unsigned long)*val, *rel));
+}
+
+/* Routines to fill sections contents during tir/etir read. */
+
+/* Initialize image buffer pointer to be filled. */
+
+static void
+image_set_ptr (bfd *abfd, bfd_vma vma, int sect, struct bfd_link_info *info)
+{
+ asection *sec;
+
+ vms_debug2 ((4, "image_set_ptr (0x%08x, sect=%d)\n", (unsigned)vma, sect));
+
+ sec = PRIV (sections)[sect];
+
+ if (info)
+ {
+ /* Reading contents to an output bfd. */
+
+ if (sec->output_section == NULL)
+ {
+ /* Section discarded. */
+ vms_debug2 ((5, " section %s discarded\n", sec->name));
+
+ /* This is not used. */
+ PRIV (image_section) = NULL;
+ PRIV (image_offset) = 0;
+ return;
+ }
+ PRIV (image_offset) = sec->output_offset + vma;
+ PRIV (image_section) = sec->output_section;
+ }
+ else
+ {
+ PRIV (image_offset) = vma;
+ PRIV (image_section) = sec;
+ }
+}
+
+/* Increment image buffer pointer by offset. */
+
+static void
+image_inc_ptr (bfd *abfd, bfd_vma offset)
+{
+ vms_debug2 ((4, "image_inc_ptr (%u)\n", (unsigned)offset));
+
+ PRIV (image_offset) += offset;
+}
+
+/* Save current DST location counter under specified index. */
+
+static void
+dst_define_location (bfd *abfd, unsigned int loc)
+{
+ vms_debug2 ((4, "dst_define_location (%d)\n", (int)loc));
+
+ /* 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_offset);
+}
+
+/* Restore saved DST location counter from specified index. */
+
+static void
+dst_restore_location (bfd *abfd, unsigned int loc)
+{
+ vms_debug2 ((4, "dst_restore_location (%d)\n", (int)loc));
+
+ PRIV (image_offset) = PRIV (dst_ptr_offsets)[loc];
+}
+
+/* Retrieve saved DST location counter from specified index. */
+
+static unsigned int
+dst_retrieve_location (bfd *abfd, unsigned int loc)
+{
+ vms_debug2 ((4, "dst_retrieve_location (%d)\n", (int)loc));
+
+ 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 *section = PRIV (image_section);
+
+ section->size += size;
+
+ /* Grow the section as necessary */
+ if (section->size <= section->rawsize)
+ return;
+ do
+ {
+ if (section->rawsize == 0)
+ section->rawsize = 1024;
+ else
+ section->rawsize *= 2;
+ }
+ while (section->size > section->rawsize);
+ section->contents = bfd_realloc (section->contents, section->rawsize);
+}
+
+/* Write multiple bytes to section image. */
+
+static bfd_boolean
+image_write (bfd *abfd, unsigned char *ptr, int size)
+{
+#if VMS_DEBUG
+ _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size,
+ (long)PRIV (image_offset));
+ _bfd_hexdump (9, ptr, size, 0);
+#endif
+
+ if (PRIV (image_autoextend))
+ dst_check_allocation (abfd, size);
+
+ if (PRIV (image_section)->contents != NULL)
+ {
+ asection *sec = PRIV (image_section);
+ file_ptr off = PRIV (image_offset);
+
+ /* Check bounds. */
+ if (off > (file_ptr)sec->size
+ || size > (file_ptr)sec->size
+ || off + size > (file_ptr)sec->size)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ memcpy (sec->contents + off, ptr, size);
+ }
+
+ PRIV (image_offset) += size;
+ return TRUE;
+}
+
+/* Write byte to section image. */
+
+static bfd_boolean
+image_write_b (bfd * abfd, unsigned int value)
+{
+ unsigned char data[1];
+
+ vms_debug2 ((6, "image_write_b (%02x)\n", (int) value));
+
+ *data = value;
+
+ return image_write (abfd, data, sizeof (data));
+}
+
+/* Write 2-byte word to image. */
+
+static bfd_boolean
+image_write_w (bfd * abfd, unsigned int value)
+{
+ unsigned char data[2];
+
+ vms_debug2 ((6, "image_write_w (%04x)\n", (int) value));
+
+ bfd_putl16 (value, data);
+ return image_write (abfd, data, sizeof (data));
+}
+
+/* Write 4-byte long to image. */
+
+static bfd_boolean
+image_write_l (bfd * abfd, unsigned long value)
+{
+ unsigned char data[4];
+
+ vms_debug2 ((6, "image_write_l (%08lx)\n", value));
+
+ bfd_putl32 (value, data);
+ return image_write (abfd, data, sizeof (data));
+}
+
+/* Write 8-byte quad to image. */
+
+static bfd_boolean
+image_write_q (bfd * abfd, bfd_vma value)
+{
+ unsigned char data[8];
+
+ vms_debug2 ((6, "image_write_q (%08lx)\n", (unsigned long)value));
+
+ bfd_putl64 (value, data);
+ return image_write (abfd, data, sizeof (data));
+}
+\f
+static const char *
+_bfd_vms_etir_name (int cmd)
+{
+ switch (cmd)
+ {
+ case ETIR__C_STA_GBL: return "ETIR__C_STA_GBL";
+ case ETIR__C_STA_LW: return "ETIR__C_STA_LW";
+ case ETIR__C_STA_QW: return "ETIR__C_STA_QW";
+ case ETIR__C_STA_PQ: return "ETIR__C_STA_PQ";
+ case ETIR__C_STA_LI: return "ETIR__C_STA_LI";
+ case ETIR__C_STA_MOD: return "ETIR__C_STA_MOD";
+ case ETIR__C_STA_CKARG: return "ETIR__C_STA_CKARG";
+ case ETIR__C_STO_B: return "ETIR__C_STO_B";
+ case ETIR__C_STO_W: return "ETIR__C_STO_W";
+ case ETIR__C_STO_GBL: return "ETIR__C_STO_GBL";
+ case ETIR__C_STO_CA: return "ETIR__C_STO_CA";
+ case ETIR__C_STO_RB: return "ETIR__C_STO_RB";
+ case ETIR__C_STO_AB: return "ETIR__C_STO_AB";
+ case ETIR__C_STO_OFF: return "ETIR__C_STO_OFF";
+ case ETIR__C_STO_IMM: return "ETIR__C_STO_IMM";
+ case ETIR__C_STO_IMMR: return "ETIR__C_STO_IMMR";
+ case ETIR__C_STO_LW: return "ETIR__C_STO_LW";
+ case ETIR__C_STO_QW: return "ETIR__C_STO_QW";
+ case ETIR__C_STO_GBL_LW: return "ETIR__C_STO_GBL_LW";
+ case ETIR__C_STO_LP_PSB: return "ETIR__C_STO_LP_PSB";
+ case ETIR__C_STO_HINT_GBL: return "ETIR__C_STO_HINT_GBL";
+ case ETIR__C_STO_HINT_PS: return "ETIR__C_STO_HINT_PS";
+ case ETIR__C_OPR_ADD: return "ETIR__C_OPR_ADD";
+ case ETIR__C_OPR_SUB: return "ETIR__C_OPR_SUB";
+ case ETIR__C_OPR_INSV: return "ETIR__C_OPR_INSV";
+ case ETIR__C_OPR_USH: return "ETIR__C_OPR_USH";
+ case ETIR__C_OPR_ROT: return "ETIR__C_OPR_ROT";
+ case ETIR__C_OPR_REDEF: return "ETIR__C_OPR_REDEF";
+ case ETIR__C_OPR_DFLIT: return "ETIR__C_OPR_DFLIT";
+ case ETIR__C_STC_LP: return "ETIR__C_STC_LP";
+ case ETIR__C_STC_GBL: return "ETIR__C_STC_GBL";
+ case ETIR__C_STC_GCA: return "ETIR__C_STC_GCA";
+ case ETIR__C_STC_PS: return "ETIR__C_STC_PS";
+ case ETIR__C_STC_NBH_PS: return "ETIR__C_STC_NBH_PS";
+ case ETIR__C_STC_NOP_GBL: return "ETIR__C_STC_NOP_GBL";
+ case ETIR__C_STC_NOP_PS: return "ETIR__C_STC_NOP_PS";
+ case ETIR__C_STC_BSR_GBL: return "ETIR__C_STC_BSR_GBL";
+ case ETIR__C_STC_BSR_PS: return "ETIR__C_STC_BSR_PS";
+ case ETIR__C_STC_LDA_GBL: return "ETIR__C_STC_LDA_GBL";
+ case ETIR__C_STC_LDA_PS: return "ETIR__C_STC_LDA_PS";
+ case ETIR__C_STC_BOH_GBL: return "ETIR__C_STC_BOH_GBL";
+ case ETIR__C_STC_BOH_PS: return "ETIR__C_STC_BOH_PS";
+ case ETIR__C_STC_NBH_GBL: return "ETIR__C_STC_NBH_GBL";
+ case ETIR__C_STC_LP_PSB: return "ETIR__C_STC_LP_PSB";
+ case ETIR__C_CTL_SETRB: return "ETIR__C_CTL_SETRB";
+ case ETIR__C_CTL_AUGRB: return "ETIR__C_CTL_AUGRB";
+ case ETIR__C_CTL_DFLOC: return "ETIR__C_CTL_DFLOC";
+ case ETIR__C_CTL_STLOC: return "ETIR__C_CTL_STLOC";
+ case ETIR__C_CTL_STKDL: return "ETIR__C_CTL_STKDL";
+
+ default:
+ /* These names have not yet been added to this switch statement. */
+ (*_bfd_error_handler) (_("unknown ETIR command %d"), cmd);
+ }
+
+ return NULL;
+}
+#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
+
+static void
+_bfd_vms_get_value (bfd *abfd, const unsigned char *ascic,
+ struct bfd_link_info *info,
+ bfd_vma *vma,
+ struct alpha_vms_link_hash_entry **hp)
+{
+ char name[257];
+ int len;
+ int i;
+ struct alpha_vms_link_hash_entry *h;
+
+ /* Not linking. Do not try to resolve the symbol. */
+ if (info == NULL)
+ {
+ *vma = 0;
+ *hp = NULL;
+ return;
+ }
+
+ len = *ascic;
+ for (i = 0; i < len; i++)
+ name[i] = ascic[i + 1];
+ name[i] = 0;
+
+ h = (struct alpha_vms_link_hash_entry *)
+ bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
+
+ *hp = h;
+
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ *vma = h->root.u.def.value
+ + h->root.u.def.section->output_offset
+ + h->root.u.def.section->output_section->vma;
+ else if (h && h->root.type == bfd_link_hash_undefweak)
+ *vma = 0;
+ else
+ {
+ if (!(*info->callbacks->undefined_symbol)
+ (info, name, abfd, PRIV (image_section), PRIV (image_offset), TRUE))
+ abort ();
+ *vma = 0;
+ }
+}
+
+#define RELC_NONE 0
+#define RELC_REL 1
+#define RELC_SHR_BASE 0x10000
+#define RELC_SEC_BASE 0x20000
+#define RELC_MASK 0x0ffff
+
+static unsigned int
+alpha_vms_sym_to_ctxt (struct alpha_vms_link_hash_entry *h)
+{
+ /* Handle undefined symbols. */
+ if (h == NULL || h->sym == NULL)
+ return RELC_NONE;
+
+ if (h->sym->typ == EGSD__C_SYMG)
+ {
+ if (h->sym->flags & EGSY__V_REL)
+ return RELC_SHR_BASE + PRIV2 (h->sym->owner, shr_index);
+ else
+ {
+ /* Can this happen ? I'd like to see an example. */
+ abort ();
+ }
+ }
+ if (h->sym->typ == EGSD__C_SYM)
+ {
+ if (h->sym->flags & EGSY__V_REL)
+ return RELC_REL;
+ else
+ return RELC_NONE;
+ }
+ abort ();
+}
+
+static bfd_vma
+alpha_vms_get_sym_value (unsigned int sect, bfd_vma addr,
+ struct alpha_vms_link_hash_entry *h)
+{
+ asection *s;
+
+ BFD_ASSERT (h && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak));
+
+ s = PRIV2 (h->root.u.def.section->owner, sections)[sect];
+ return s->output_section->vma + s->output_offset + addr;
+}
+
+static bfd_vma
+alpha_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info,
+ unsigned int rel, bfd_vma vma)
+{
+ asection *sec = PRIV (sections)[rel & RELC_MASK];
+
+ if (info)
+ {
+ if (sec->output_section == NULL)
+ abort ();
+ return vma + sec->output_section->vma + sec->output_offset;
+ }
+ else
+ return vma + sec->vma;
+}
+
+static bfd_boolean
+_bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
+{
+ unsigned char *ptr;
+ unsigned int length;
+ unsigned char *maxptr;
+ bfd_vma op1;
+ bfd_vma op2;
+ unsigned int rel1;
+ unsigned int rel2;
+ struct alpha_vms_link_hash_entry *h;
+
+ PRIV (recrd.rec) += ETIR__C_HEADER_SIZE;
+ PRIV (recrd.rec_size) -= ETIR__C_HEADER_SIZE;
+
+ ptr = PRIV (recrd.rec);
+ length = PRIV (recrd.rec_size);
+ maxptr = ptr + length;
+
+ vms_debug2 ((2, "ETIR: %d bytes\n", length));
+
+ while (ptr < maxptr)
+ {
+ int cmd = bfd_getl16 (ptr);
+ int cmd_length = bfd_getl16 (ptr + 2);
+
+ ptr += 4;
+
+#if VMS_DEBUG
+ _bfd_vms_debug (4, "etir: %s(%d)\n",
+ _bfd_vms_etir_name (cmd), cmd);
+ _bfd_hexdump (8, ptr, cmd_length - 4, (long) ptr);
+#endif
+
+ switch (cmd)
+ {
+ /* Stack global
+ arg: cs symbol name
+
+ stack 32 bit value of symbol (high bits set to 0). */
+ case ETIR__C_STA_GBL:
+ _bfd_vms_get_value (abfd, ptr, info, &op1, &h);
+ _bfd_vms_push (abfd, op1, alpha_vms_sym_to_ctxt (h));
+ break;
+
+ /* Stack longword
+ arg: lw value
+
+ stack 32 bit value, sign extend to 64 bit. */
+ case ETIR__C_STA_LW:
+ _bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE);
+ break;
+
+ /* Stack quadword
+ arg: qw value
+
+ stack 64 bit value of symbol. */
+ case ETIR__C_STA_QW:
+ _bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE);
+ break;
+
+ /* Stack psect base plus quadword offset
+ arg: lw section index
+ qw signed quadword offset (low 32 bits)
+
+ Stack qw argument and section index
+ (see ETIR__C_STO_OFF, ETIR__C_CTL_SETRB). */
+ case ETIR__C_STA_PQ:
+ {
+ int psect;
+
+ psect = bfd_getl32 (ptr);
+ if ((unsigned int) psect >= PRIV (section_count))
+ {
+ (*_bfd_error_handler) (_("bad section index in %s"),
+ _bfd_vms_etir_name (cmd));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ op1 = bfd_getl64 (ptr + 4);
+ _bfd_vms_push (abfd, op1, psect | RELC_SEC_BASE);
+ }
+ break;
+
+ case ETIR__C_STA_LI:
+ case ETIR__C_STA_MOD:
+ case ETIR__C_STA_CKARG:
+ (*_bfd_error_handler) (_("unsupported STA cmd %s"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ break;
+
+ /* Store byte: pop stack, write byte
+ arg: -. */
+ case ETIR__C_STO_B:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ image_write_b (abfd, (unsigned int) op1 & 0xff);
+ break;
+
+ /* Store word: pop stack, write word
+ arg: -. */
+ case ETIR__C_STO_W:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ image_write_w (abfd, (unsigned int) op1 & 0xffff);
+ break;
+
+ /* Store longword: pop stack, write longword
+ arg: -. */
+ case ETIR__C_STO_LW:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 & RELC_SEC_BASE)
+ {
+ op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
+ rel1 = RELC_REL;
+ }
+ else if (rel1 & RELC_SHR_BASE)
+ {
+ alpha_vms_add_lw_fixup (info, rel1 & RELC_MASK, op1);
+ rel1 = RELC_NONE;
+ }
+ if (rel1 != RELC_NONE)
+ {
+ if (rel1 != RELC_REL)
+ abort ();
+ alpha_vms_add_lw_reloc (info);
+ }
+ image_write_l (abfd, op1);
+ break;
+
+ /* Store quadword: pop stack, write quadword
+ arg: -. */
+ case ETIR__C_STO_QW:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 & RELC_SEC_BASE)
+ {
+ op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
+ rel1 = RELC_REL;
+ }
+ else if (rel1 & RELC_SHR_BASE)
+ abort ();
+ if (rel1 != RELC_NONE)
+ {
+ if (rel1 != RELC_REL)
+ abort ();
+ alpha_vms_add_qw_reloc (info);
+ }
+ image_write_q (abfd, op1);
+ break;
+
+ /* Store immediate repeated: pop stack for repeat count
+ arg: lw byte count
+ da data. */
+ case ETIR__C_STO_IMMR:
+ {
+ int size;
+
+ size = bfd_getl32 (ptr);
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ while (op1-- > 0)
+ image_write (abfd, ptr + 4, size);
+ }
+ break;
+
+ /* Store global: write symbol value
+ arg: cs global symbol name. */
+ case ETIR__C_STO_GBL:
+ _bfd_vms_get_value (abfd, ptr, info, &op1, &h);
+ if (h && h->sym)
+ {
+ if (h->sym->typ == EGSD__C_SYMG)
+ {
+ alpha_vms_add_fixup_qr
+ (info, abfd, h->sym->owner, h->sym->symbol_vector);
+ op1 = 0;
+ }
+ else
+ {
+ op1 = alpha_vms_get_sym_value (h->sym->section,
+ h->sym->value, h);
+ alpha_vms_add_qw_reloc (info);
+ }
+ }
+ image_write_q (abfd, op1);
+ break;
+
+ /* Store code address: write address of entry point
+ arg: cs global symbol name (procedure). */
+ case ETIR__C_STO_CA:
+ _bfd_vms_get_value (abfd, ptr, info, &op1, &h);
+ if (h && h->sym)
+ {
+ if (h->sym->flags & EGSY__V_NORM)
+ {
+ /* That's really a procedure. */
+ if (h->sym->typ == EGSD__C_SYMG)
+ {
+ alpha_vms_add_fixup_ca (info, abfd, h->sym->owner);
+ op1 = h->sym->symbol_vector;
+ }
+ else
+ {
+ op1 = alpha_vms_get_sym_value (h->sym->code_section,
+ h->sym->code_value, h);
+ alpha_vms_add_qw_reloc (info);
+ }
+ }
+ else
+ {
+ /* Symbol is not a procedure. */
+ abort ();
+ }
+ }
+ image_write_q (abfd, op1);
+ break;
+
+ /* Store offset to psect: pop stack, add low 32 bits to base of psect
+ arg: none. */
+ case ETIR__C_STO_OFF:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+
+ if (!(rel1 & RELC_SEC_BASE))
+ abort ();
+
+ op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
+ rel1 = RELC_REL;
+ image_write_q (abfd, op1);
+ break;
+
+ /* Store immediate
+ arg: lw count of bytes
+ da data. */
+ case ETIR__C_STO_IMM:
+ {
+ int size;
+
+ size = bfd_getl32 (ptr);
+ image_write (abfd, ptr + 4, size);
+ }
+ break;
+
+ /* This code is 'reserved to digital' according to the openVMS
+ linker manual, however it is generated by the DEC C compiler
+ and defined in the include file.
+ FIXME, since the following is just a guess
+ store global longword: store 32bit value of symbol
+ arg: cs symbol name. */
+ case ETIR__C_STO_GBL_LW:
+ _bfd_vms_get_value (abfd, ptr, info, &op1, &h);
+#if 0
+ abort ();
+#endif
+ image_write_l (abfd, op1);
+ break;
+
+ case ETIR__C_STO_RB:
+ case ETIR__C_STO_AB:
+ case ETIR__C_STO_LP_PSB:
+ (*_bfd_error_handler) (_("%s: not supported"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ break;
+ case ETIR__C_STO_HINT_GBL:
+ case ETIR__C_STO_HINT_PS:
+ (*_bfd_error_handler) (_("%s: not implemented"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ break;
+
+ /* 200 Store-conditional Linkage Pair
+ arg: none. */
+ case ETIR__C_STC_LP:
+
+ /* 202 Store-conditional Address at global address
+ lw linkage index
+ cs global name. */
+
+ case ETIR__C_STC_GBL:
+
+ /* 203 Store-conditional Code Address at global address
+ lw linkage index
+ cs procedure name. */
+ case ETIR__C_STC_GCA:
+
+ /* 204 Store-conditional Address at psect + offset
+ lw linkage index
+ lw psect index
+ qw offset. */
+ case ETIR__C_STC_PS:
+ (*_bfd_error_handler) (_("%s: not supported"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ break;
+
+ /* 201 Store-conditional Linkage Pair with Procedure Signature
+ lw linkage index
+ cs procedure name
+ by signature length
+ da signature. */
+
+ case ETIR__C_STC_LP_PSB:
+ _bfd_vms_get_value (abfd, ptr + 4, info, &op1, &h);
+ if (h && h->sym)
+ {
+ if (h->sym->typ == EGSD__C_SYMG)
+ {
+ alpha_vms_add_fixup_lp (info, abfd, h->sym->owner);
+ op1 = h->sym->symbol_vector;
+ op2 = 0;
+ }
+ else
+ {
+ op1 = alpha_vms_get_sym_value (h->sym->code_section,
+ h->sym->code_value, h);
+ op2 = alpha_vms_get_sym_value (h->sym->section,
+ h->sym->value, h);
+ }
+ }
+ else
+ {
+ /* Undefined symbol. */
+ op1 = 0;
+ op2 = 0;
+ }
+ image_write_q (abfd, op1);
+ image_write_q (abfd, op2);
+ break;
+
+ /* 205 Store-conditional NOP at address of global
+ arg: none. */
+ case ETIR__C_STC_NOP_GBL:
+ /* ALPHA_R_NOP */
+
+ /* 207 Store-conditional BSR at global address
+ arg: none. */
+
+ case ETIR__C_STC_BSR_GBL:
+ /* ALPHA_R_BSR */
+
+ /* 209 Store-conditional LDA at global address
+ arg: none. */
+
+ case ETIR__C_STC_LDA_GBL:
+ /* ALPHA_R_LDA */
+
+ /* 211 Store-conditional BSR or Hint at global address
+ arg: none. */
+
+ case ETIR__C_STC_BOH_GBL:
+ /* Currentl ignored. */
+ break;
+
+ /* 213 Store-conditional NOP,BSR or HINT at global address
+ arg: none. */
+
+ case ETIR__C_STC_NBH_GBL:
+
+ /* 206 Store-conditional NOP at pect + offset
+ arg: none. */
+
+ case ETIR__C_STC_NOP_PS:
+
+ /* 208 Store-conditional BSR at pect + offset
+ arg: none. */
+
+ case ETIR__C_STC_BSR_PS:
+
+ /* 210 Store-conditional LDA at psect + offset
+ arg: none. */
+
+ case ETIR__C_STC_LDA_PS:
+
+ /* 212 Store-conditional BSR or Hint at pect + offset
+ arg: none. */
+
+ case ETIR__C_STC_BOH_PS:
+
+ /* 214 Store-conditional NOP, BSR or HINT at psect + offset
+ arg: none. */
+ case ETIR__C_STC_NBH_PS:
+ (*_bfd_error_handler) ("%s: not supported",
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ break;
+
+ /* Det relocation base: pop stack, set image location counter
+ arg: none. */
+ case ETIR__C_CTL_SETRB:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (!(rel1 & RELC_SEC_BASE))
+ abort ();
+ image_set_ptr (abfd, op1, rel1 & RELC_MASK, info);
+ break;
+
+ /* Augment relocation base: increment image location counter by offset
+ arg: lw offset value. */
+ case ETIR__C_CTL_AUGRB:
+ op1 = bfd_getl32 (ptr);
+ image_inc_ptr (abfd, op1);
+ break;
+
+ /* Define location: pop index, save location counter under index
+ arg: none. */
+ case ETIR__C_CTL_DFLOC:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ dst_define_location (abfd, op1);
+ break;
+
+ /* Set location: pop index, restore location counter from index
+ arg: none. */
+ case ETIR__C_CTL_STLOC:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ dst_restore_location (abfd, op1);
+ break;
+
+ /* Stack defined location: pop index, push location counter from index
+ arg: none. */
+ case ETIR__C_CTL_STKDL:
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, dst_retrieve_location (abfd, op1), RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_NOP: /* No-op. */
+ break;
+
+ case ETIR__C_OPR_ADD: /* Add. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 == RELC_NONE && rel2 != RELC_NONE)
+ rel1 = rel2;
+ else if (rel1 != RELC_NONE && rel2 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, op1 + op2, rel1);
+ break;
+
+ case ETIR__C_OPR_SUB: /* Subtract. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 == RELC_NONE && rel2 != RELC_NONE)
+ rel1 = rel2;
+ else if ((rel1 & RELC_SEC_BASE) && (rel2 & RELC_SEC_BASE))
+ {
+ op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
+ op2 = alpha_vms_fix_sec_rel (abfd, info, rel2, op2);
+ rel1 = RELC_NONE;
+ }
+ else if (rel1 != RELC_NONE && rel2 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, op2 - op1, rel1);
+ break;
+
+ case ETIR__C_OPR_MUL: /* Multiply. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 != RELC_NONE || rel2 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, op1 * op2, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_DIV: /* Divide. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 != RELC_NONE || rel2 != RELC_NONE)
+ goto bad_context;
+ if (op2 == 0)
+ _bfd_vms_push (abfd, 0, RELC_NONE);
+ else
+ _bfd_vms_push (abfd, op2 / op1, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_AND: /* Logical AND. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 != RELC_NONE || rel2 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, op1 & op2, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_IOR: /* Logical inclusive OR. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 != RELC_NONE || rel2 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, op1 | op2, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_EOR: /* Logical exclusive OR. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 != RELC_NONE || rel2 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, op1 ^ op2, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_NEG: /* Negate. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, -op1, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_COM: /* Complement. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (rel1 != RELC_NONE)
+ goto bad_context;
+ _bfd_vms_push (abfd, ~op1, RELC_NONE);
+ break;
+
+ case ETIR__C_OPR_ASH: /* Arithmetic shift. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ if (rel1 != RELC_NONE || rel2 != RELC_NONE)
+ {
+ bad_context:
+ (*_bfd_error_handler) (_("invalid use of %s with contexts"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ }
+ if ((int)op2 < 0) /* Shift right. */
+ op1 >>= -(int)op2;
+ else /* Shift left. */
+ op1 <<= (int)op2;
+ _bfd_vms_push (abfd, op1, RELC_NONE); /* FIXME: sym. */
+ break;
+
+ case ETIR__C_OPR_INSV: /* Insert field. */
+ case ETIR__C_OPR_USH: /* Unsigned shift. */
+ case ETIR__C_OPR_ROT: /* Rotate. */
+ case ETIR__C_OPR_REDEF: /* Redefine symbol to current location. */
+ case ETIR__C_OPR_DFLIT: /* Define a literal. */
+ (*_bfd_error_handler) (_("%s: not supported"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ break;
+
+ case ETIR__C_OPR_SEL: /* Select. */
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ if (op1 & 0x01L)
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ else
+ {
+ _bfd_vms_pop (abfd, &op1, &rel1);
+ _bfd_vms_pop (abfd, &op2, &rel2);
+ _bfd_vms_push (abfd, op1, rel1);
+ }
+ break;
+
+ default:
+ (*_bfd_error_handler) (_("reserved cmd %d"), cmd);
+ return FALSE;
+ break;
+ }
+
+ ptr += cmd_length - 4;
+ }
+
+ return TRUE;
+}
+
+/* Process EDBG/ETBT record.
+ Return TRUE on success, FALSE on error */
+
+static bfd_boolean
+vms_slurp_debug (bfd *abfd)
+{
+ asection *section = PRIV (dst_section);
+
+ if (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
+ | SEC_IN_MEMORY;
+
+ section = bfd_make_section (abfd, "$DST$");
+ if (!section)
+ return FALSE;
+ if (!bfd_set_section_flags (abfd, section, flags))
+ return FALSE;
+ PRIV (dst_section) = section;
+ }
+
+ PRIV (image_section) = section;
+ PRIV (image_offset) = section->size;
+ PRIV (image_autoextend) = FALSE;
+
+ if (!_bfd_vms_slurp_etir (abfd, NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Process EDBG record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_edbg (bfd *abfd)
+{
+ vms_debug2 ((2, "EDBG\n"));
+
+ abfd->flags |= (HAS_DEBUG | HAS_LINENO);
+
+ return vms_slurp_debug (abfd);
+}
+
+/* Process ETBT record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_etbt (bfd *abfd)
+{
+ vms_debug2 ((2, "ETBT\n"));
+
+ abfd->flags |= HAS_LINENO;
+
+ return vms_slurp_debug (abfd);
+}
+
+/* Process EEOM record.
+ Return TRUE on success, FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_eeom (bfd *abfd)
+{
+ struct vms_eeom *eeom = (struct vms_eeom *) PRIV (recrd.rec);
+
+ vms_debug2 ((2, "EEOM\n"));
+
+ PRIV (eom_data).eom_l_total_lps = bfd_getl32 (eeom->total_lps);
+ PRIV (eom_data).eom_w_comcod = bfd_getl16 (eeom->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);
+ return FALSE;
+ }
+
+ PRIV (eom_data).eom_has_transfer = FALSE;
+ if (PRIV (recrd.rec_size) > 10)
+ {
+ PRIV (eom_data).eom_has_transfer = TRUE;
+ PRIV (eom_data).eom_b_tfrflg = eeom->tfrflg;
+ PRIV (eom_data).eom_l_psindx = bfd_getl32 (eeom->psindx);
+ PRIV (eom_data).eom_l_tfradr = bfd_getl32 (eeom->tfradr);
+
+ abfd->start_address = PRIV (eom_data).eom_l_tfradr;
+ }
+ return TRUE;
+}
+
+/* Slurp an ordered set of VMS object records. Return FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_slurp_object_records (bfd * abfd)
+{
+ int err, new_type, type = -1;
+
+ do
+ {
+ vms_debug2 ((7, "reading at %08lx\n", (unsigned long)bfd_tell (abfd)));
+
+ new_type = _bfd_vms_get_object_record (abfd);
+ if (new_type < 0)
+ {
+ vms_debug2 ((2, "next_record failed\n"));
+ return FALSE;
+ }
+
+ type = new_type;
+
+ switch (type)
+ {
+ case EOBJ__C_EMH:
+ err = _bfd_vms_slurp_ehdr (abfd);
+ break;
+ case EOBJ__C_EEOM:
+ err = _bfd_vms_slurp_eeom (abfd);
+ break;
+ case EOBJ__C_EGSD:
+ err = _bfd_vms_slurp_egsd (abfd);
+ break;
+ case EOBJ__C_ETIR:
+ err = TRUE; /* _bfd_vms_slurp_etir (abfd); */
+ break;
+ case EOBJ__C_EDBG:
+ err = _bfd_vms_slurp_edbg (abfd);
+ break;
+ case EOBJ__C_ETBT:
+ err = _bfd_vms_slurp_etbt (abfd);
+ break;
+ default:
+ err = FALSE;
+ }
+ if (err != TRUE)
+ {
+ vms_debug2 ((2, "slurp type %d failed\n", type));
+ return FALSE;
+ }
+ }
+ while (type != EOBJ__C_EEOM);
+
+ return TRUE;
+}
+
+/* Initialize private data */
+static bfd_boolean
+vms_initialize (bfd * abfd)
+{
+ bfd_size_type amt;
+
+ amt = sizeof (struct vms_private_data_struct);
+ abfd->tdata.any = bfd_zalloc (abfd, amt);
+ if (abfd->tdata.any == NULL)
+ return FALSE;
+
+ PRIV (recrd.file_format) = FF_UNKNOWN;
+
+ amt = sizeof (struct stack_struct) * STACKSIZE;
+ PRIV (stack) = bfd_alloc (abfd, amt);
+ if (PRIV (stack) == NULL)
+ goto error_ret1;
+
+ return TRUE;
+
+ error_ret1:
+ bfd_release (abfd, abfd->tdata.any);
+ abfd->tdata.any = NULL;
+ return FALSE;
+}
+
+/* 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 *
+alpha_vms_object_p (bfd *abfd)
+{
+ PTR tdata_save = abfd->tdata.any;
+ unsigned int test_len;
+ unsigned char *buf;
+
+ vms_debug2 ((1, "vms_object_p(%p)\n", abfd));
+
+ /* Allocate alpha-vms specific data. */
+ if (!vms_initialize (abfd))
+ goto error_ret;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
+ goto err_wrong_format;
+
+ /* The first challenge with VMS is to discover the kind of the file.
+
+ Image files (executable or shared images) are stored as a raw
+ stream of bytes (like on UNIX), but there is no magic number.
+
+ Object files are written with RMS (record management service), ie
+ each records are preceeded by its length (on a word - 2 bytes), and
+ padded for word-alignment. That would be simple but when files
+ are transfered to a UNIX filesystem (using ftp), records are lost.
+ Only the raw content of the records are transfered. Fortunately,
+ the Alpha Object file format also store the length of the record
+ in the records. Is that clear ? */
+
+ /* 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. */
+ buf = (unsigned char *) bfd_malloc (test_len);
+ if (buf == NULL)
+ goto error_ret;
+ PRIV (recrd.buf) = buf;
+ PRIV (recrd.buf_size) = test_len;
+
+ /* Initialize the record pointer. */
+ PRIV (recrd.rec) = buf;
+
+ if (bfd_bread (buf, test_len, abfd) != test_len)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ goto error_ret;
+ }
+
+ /* Is it an image? */
+ if ((bfd_getl32 (buf) == EIHD__K_MAJORID)
+ && (bfd_getl32 (buf + 4) == EIHD__K_MINORID))
+ {
+ unsigned int to_read;
+ unsigned int read_so_far;
+ unsigned int remaining;
+ unsigned int eisd_offset, eihs_offset;
+
+ /* Extract the header size. */
+ PRIV (recrd.rec_size) = bfd_getl32 (buf + EIHD__L_SIZE);
+
+ if (PRIV (recrd.rec_size) > PRIV (recrd.buf_size))
+ {
+ buf = bfd_realloc_or_free (buf, PRIV (recrd.rec_size));
+
+ if (buf == NULL)
+ {
+ PRIV (recrd.buf) = NULL;
+ bfd_set_error (bfd_error_no_memory);
+ goto error_ret;
+ }
+ PRIV (recrd.buf) = buf;
+ PRIV (recrd.buf_size) = PRIV (recrd.rec_size);
+ }
+
+ /* Read the remaining record. */
+ remaining = PRIV (recrd.rec_size) - test_len;
+ to_read = MIN (VMS_BLOCK_SIZE - test_len, remaining);
+ read_so_far = test_len;
+
+ while (remaining > 0)
+ {
+ if (bfd_bread (buf + read_so_far, to_read, abfd) != to_read)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ goto err_wrong_format;
+ }
+
+ read_so_far += to_read;
+ remaining -= to_read;
+
+ to_read = MIN (VMS_BLOCK_SIZE, remaining);
+ }
+
+ /* Reset the record pointer. */
+ PRIV (recrd.rec) = buf;
+
+ vms_debug2 ((2, "file type is image\n"));
+
+ if (_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset) != TRUE)
+ goto err_wrong_format;
+
+ if (_bfd_vms_slurp_eisd (abfd, eisd_offset) != TRUE)
+ goto err_wrong_format;
+
+ /* EIHS is optional. */
+ if (eihs_offset != 0 && _bfd_vms_slurp_eihs (abfd, eihs_offset) != TRUE)
+ goto err_wrong_format;
+ }
+ else
+ {
+ int type;
+
+ /* 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 (recrd.rec)) <= EOBJ__C_MAXRECTYP
+ && bfd_getl16 (PRIV (recrd.rec) + 2) <= EOBJ__C_MAXRECSIZ)
+ {
+ if (vms_get_remaining_object_record (abfd, test_len) <= 0)
+ goto err_wrong_format;
+
+ vms_debug2 ((2, "file type is module\n"));
+
+ type = bfd_getl16 (PRIV (recrd.rec));
+ if (type != EOBJ__C_EMH || _bfd_vms_slurp_ehdr (abfd) != TRUE)
+ goto err_wrong_format;
+
+ if (_bfd_vms_slurp_object_records (abfd) != TRUE)
+ goto err_wrong_format;
+ }
+ else
+ goto err_wrong_format;
+ }
+
+ /* Set arch_info to alpha. */
+
+ if (! bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0))
+ goto err_wrong_format;
+
+ return abfd->xvec;
+
+ err_wrong_format:
+ bfd_set_error (bfd_error_wrong_format);
+
+ error_ret:
+ if (PRIV (recrd.buf))
+ free (PRIV (recrd.buf));
+ if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
+ bfd_release (abfd, abfd->tdata.any);
+ abfd->tdata.any = tdata_save;
+ return NULL;
+}
+\f
+/* Image write. */
+
+static void
+vector_grow1 (struct vector_type *vec, size_t elsz)
+{
+ if (vec->nbr_el + 1 < vec->max_el)
+ return;
+
+ if (vec->max_el == 0)
+ {
+ vec->max_el = 16;
+ vec->els = bfd_malloc2 (vec->max_el, elsz);
+ }
+ else
+ {
+ vec->max_el *= 2;
+ vec->els = bfd_realloc2 (vec->els, vec->max_el, elsz);
+ }
+}
+
+/* Bump ABFD file position to next block. */
+
+static void
+alpha_vms_file_position_block (bfd *abfd)
+{
+ /* Next block. */
+ PRIV (file_pos) += VMS_BLOCK_SIZE - 1;
+ PRIV (file_pos) -= (PRIV (file_pos) % VMS_BLOCK_SIZE);
+}
+
+static void
+alpha_vms_swap_eisd_out (struct vms_internal_eisd_map *src,
+ struct vms_eisd *dst)
+{
+ bfd_putl32 (src->u.eisd.majorid, dst->majorid);
+ bfd_putl32 (src->u.eisd.minorid, dst->minorid);
+ bfd_putl32 (src->u.eisd.eisdsize, dst->eisdsize);
+ if (src->u.eisd.eisdsize <= EISD__K_LENEND)
+ return;
+ bfd_putl32 (src->u.eisd.secsize, dst->secsize);
+ bfd_putl64 (src->u.eisd.virt_addr, dst->virt_addr);
+ bfd_putl32 (src->u.eisd.flags, dst->flags);
+ bfd_putl32 (src->u.eisd.vbn, dst->vbn);
+ dst->pfc = src->u.eisd.pfc;
+ dst->matchctl = src->u.eisd.matchctl;
+ dst->type = src->u.eisd.type;
+ dst->fill_1 = 0;
+ if (src->u.eisd.flags & EISD__M_GBL)
+ {
+ bfd_putl32 (src->u.gbl_eisd.ident, dst->ident);
+ memcpy (dst->gblnam, src->u.gbl_eisd.gblnam,
+ src->u.gbl_eisd.gblnam[0] + 1);
+ }
+}
+
+/* Append EISD to the list of extra eisd for ABFD. */
+
+static void
+alpha_vms_append_extra_eisd (bfd *abfd, struct vms_internal_eisd_map *eisd)
+{
+ eisd->next = NULL;
+ if (PRIV (gbl_eisd_head) == NULL)
+ PRIV (gbl_eisd_head) = eisd;
+ else
+ PRIV (gbl_eisd_tail)->next = eisd;
+ PRIV (gbl_eisd_tail) = eisd;
+}
+
+static bfd_boolean
+alpha_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg)
+{
+ struct vms_internal_eisd_map *eisd;
+ int namlen;
+
+ namlen = strlen (PRIV2 (shrimg, hdr_data.hdr_t_name));
+ if (namlen + 5 > EISD__K_GBLNAMLEN)
+ {
+ /* Won't fit. */
+ return FALSE;
+ }
+
+ eisd = bfd_alloc (abfd, sizeof (*eisd));
+ if (eisd == NULL)
+ return FALSE;
+
+ /* Fill the fields. */
+ eisd->u.gbl_eisd.common.majorid = EISD__K_MAJORID;
+ eisd->u.gbl_eisd.common.minorid = EISD__K_MINORID;
+ eisd->u.gbl_eisd.common.eisdsize = (EISD__K_LEN + 4 + namlen + 5 + 3) & ~3;
+ eisd->u.gbl_eisd.common.secsize = VMS_BLOCK_SIZE; /* Must not be 0. */
+ eisd->u.gbl_eisd.common.virt_addr = 0;
+ eisd->u.gbl_eisd.common.flags = EISD__M_GBL;
+ eisd->u.gbl_eisd.common.vbn = 0;
+ eisd->u.gbl_eisd.common.pfc = 0;
+ eisd->u.gbl_eisd.common.matchctl = PRIV2 (shrimg, matchctl);
+ eisd->u.gbl_eisd.common.type = EISD__K_SHRPIC;
+
+ eisd->u.gbl_eisd.ident = PRIV2 (shrimg, ident);
+ eisd->u.gbl_eisd.gblnam[0] = namlen + 4;
+ memcpy (eisd->u.gbl_eisd.gblnam + 1, PRIV2 (shrimg, hdr_data.hdr_t_name),
+ namlen);
+ memcpy (eisd->u.gbl_eisd.gblnam + 1 + namlen, "_001", 4);
+
+ /* Append it to the list. */
+ alpha_vms_append_extra_eisd (abfd, eisd);
+
+ return TRUE;
+}
+
+static bfd_boolean
+alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
+{
+ struct vms_internal_eisd_map *eisd;
+
+ /* Only for allocating section. */
+ if (!(sec->flags & SEC_ALLOC))
+ return TRUE;
+
+ BFD_ASSERT (vms_section_data (sec)->eisd == NULL);
+ eisd = bfd_alloc (abfd, sizeof (*eisd));
+ if (eisd == NULL)
+ return FALSE;
+ vms_section_data (sec)->eisd = eisd;
+
+ /* Fill the fields. */
+ eisd->u.eisd.majorid = EISD__K_MAJORID;
+ eisd->u.eisd.minorid = EISD__K_MINORID;
+ eisd->u.eisd.eisdsize = EISD__K_LEN;
+ eisd->u.eisd.secsize =
+ (sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1);
+ eisd->u.eisd.virt_addr = sec->vma;
+ eisd->u.eisd.flags = 0;
+ eisd->u.eisd.vbn = 0; /* To be later defined. */
+ eisd->u.eisd.pfc = 0; /* Default. */
+ eisd->u.eisd.matchctl = EISD__K_MATALL;
+ eisd->u.eisd.type = EISD__K_NORMAL;
+
+ if (sec->flags & SEC_CODE)
+ eisd->u.eisd.flags |= EISD__M_EXE;
+ if (!(sec->flags & SEC_READONLY))
+ eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
+
+ if (!(sec->flags & SEC_LOAD))
+ {
+ eisd->u.eisd.flags |= EISD__M_DZRO;
+ eisd->u.eisd.flags &= ~EISD__M_CRF;
+ }
+ if (sec->flags & SEC_LINKER_CREATED)
+ {
+ if (strcmp (sec->name, "$FIXUP$") == 0)
+ eisd->u.eisd.flags |= EISD__M_FIXUPVEC;
+ }
+
+ /* Append it to the list. */
+ eisd->next = NULL;
+ if (PRIV (eisd_head) == NULL)
+ PRIV (eisd_head) = eisd;
+ else
+ PRIV (eisd_tail)->next = eisd;
+ PRIV (eisd_tail) = eisd;
+
+ return TRUE;
+}
+
+static bfd_boolean
+alpha_vms_write_exec (bfd *abfd)
+{
+ struct vms_eihd eihd;
+ struct vms_eiha *eiha;
+ struct vms_eihi *eihi;
+ struct vms_eihs *eihs = NULL;
+ asection *sec;
+ struct vms_internal_eisd_map *first_eisd;
+ struct vms_internal_eisd_map *eisd;
+ asection *dst;
+
+ PRIV (file_pos) = EIHD__C_LENGTH;
+
+ memset (&eihd, 0, sizeof (eihd));
+ memset (eihd.fill_2, 0xff, sizeof (eihd.fill_2));
+
+ bfd_putl32 (EIHD__K_MAJORID, eihd.majorid);
+ bfd_putl32 (EIHD__K_MINORID, eihd.minorid);
+
+ bfd_putl32 (sizeof (eihd), eihd.size);
+ bfd_putl32 (0, eihd.isdoff);
+ bfd_putl32 (0, eihd.activoff);
+ bfd_putl32 (0, eihd.symdbgoff);
+ bfd_putl32 (0, eihd.imgidoff);
+ bfd_putl32 (0, eihd.patchoff);
+ bfd_putl64 (0, eihd.iafva);
+ bfd_putl32 (0, eihd.version_array_off);
+
+ bfd_putl32 (EIHD__K_EXE, eihd.imgtype);
+ bfd_putl32 (0, eihd.subtype);
+
+ bfd_putl32 (0, eihd.imgiocnt);
+ bfd_putl32 (-1, eihd.privreqs);
+ bfd_putl32 (-1, eihd.privreqs + 4);
+
+ bfd_putl32 ((sizeof (eihd) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE,
+ eihd.hdrblkcnt);
+ bfd_putl32 (0, eihd.lnkflags);
+ bfd_putl32 (0, eihd.ident);
+ bfd_putl32 (0, eihd.sysver);
+
+ eihd.matchctl = 0;
+ bfd_putl32 (0, eihd.symvect_size);
+ bfd_putl32 (16, eihd.virt_mem_block_size);
+ bfd_putl32 (0, eihd.ext_fixup_off);
+ bfd_putl32 (0, eihd.noopt_psect_off);
+ bfd_putl32 (-1, eihd.alias);
+
+ /* Alloc EIHA. */
+ eiha = (struct vms_eiha *)((char *) &eihd + PRIV (file_pos));
+ bfd_putl32 (PRIV (file_pos), eihd.activoff);
+ PRIV (file_pos) += sizeof (struct vms_eiha);
+
+ bfd_putl32 (sizeof (struct vms_eiha), eiha->size);
+ bfd_putl32 (0, eiha->spare);
+ bfd_putl32 (0x00000340, eiha->tfradr1); /* SYS$IMGACT */
+ bfd_putl32 (0xffffffff, eiha->tfradr1_h);
+ bfd_putl64 (bfd_get_start_address (abfd), eiha->tfradr2);
+ bfd_putl64 (0, eiha->tfradr3);
+ bfd_putl64 (0, eiha->tfradr4);
+ bfd_putl64 (0, eiha->inishr);
+
+ /* Alloc EIHI. */
+ eihi = (struct vms_eihi *)((char *) &eihd + PRIV (file_pos));
+ bfd_putl32 (PRIV (file_pos), eihd.imgidoff);
+ PRIV (file_pos) += sizeof (struct vms_eihi);
+
+ bfd_putl32 (EIHI__K_MAJORID, eihi->majorid);
+ bfd_putl32 (EIHI__K_MINORID, eihi->minorid);
+ {
+ char *module;
+ unsigned int len;
+
+ module = vms_get_module_name (bfd_get_filename (abfd), TRUE);
+ len = strlen (module);
+ if (len > sizeof (eihi->imgnam) - 1)
+ len = sizeof (eihi->imgnam) - 1;
+ eihi->imgnam[0] = len;
+ memcpy (eihi->imgnam + 1, module, len);
+ free (module);
+ }
+ bfd_putl32 (0, eihi->linktime + 0);
+ bfd_putl32 (0, eihi->linktime + 4);
+ eihi->imgid[0] = 0;
+ eihi->linkid[0] = 0;
+ eihi->imgbid[0] = 0;
+
+ /* Alloc EIHS. */
+ dst = bfd_get_section_by_name (abfd, "$DST$");
+ if (dst == NULL || dst->size == 0)
+ dst = bfd_get_section_by_name (abfd, "$TBT$");
+ if (dst != NULL && dst->size != 0)
+ {
+ eihs = (struct vms_eihs *)((char *) &eihd + PRIV (file_pos));
+ bfd_putl32 (PRIV (file_pos), eihd.symdbgoff);
+ PRIV (file_pos) += sizeof (struct vms_eihs);
+
+ bfd_putl32 (EIHS__K_MAJORID, eihs->majorid);
+ bfd_putl32 (EIHS__K_MINORID, eihs->minorid);
+ bfd_putl32 (0, eihs->dstvbn);
+ bfd_putl32 (0, eihs->dstsize);
+ bfd_putl32 (0, eihs->gstvbn);
+ bfd_putl32 (0, eihs->gstsize);
+ bfd_putl32 (0, eihs->dmtvbn);
+ bfd_putl32 (0, eihs->dmtsize);
+ }
+
+ /* One per section. */
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ if (!alpha_vms_create_eisd_for_section (abfd, sec))
+ return FALSE;
+ }
+
+ /* Merge section EIDS which extra ones. */
+ if (PRIV (eisd_tail))
+ PRIV (eisd_tail)->next = PRIV (gbl_eisd_head);
+ else
+ PRIV (eisd_head) = PRIV (gbl_eisd_head);
+ if (PRIV (gbl_eisd_tail))
+ PRIV (eisd_tail) = PRIV (gbl_eisd_tail);
+
+ first_eisd = PRIV (eisd_head);
+
+ /* Add end of eisd. */
+ if (first_eisd)
+ {
+ eisd = bfd_zalloc (abfd, sizeof (*eisd));
+ if (eisd == NULL)
+ return FALSE;
+ eisd->u.eisd.majorid = 0;
+ eisd->u.eisd.minorid = 0;
+ eisd->u.eisd.eisdsize = 0;
+ alpha_vms_append_extra_eisd (abfd, eisd);
+ }
+
+ /* Place EISD in the file. */
+ for (eisd = first_eisd; eisd; eisd = eisd->next)
+ {
+ file_ptr room = VMS_BLOCK_SIZE - (PRIV (file_pos) % VMS_BLOCK_SIZE);
+
+ /* First block is a little bit special: there is a word at the end. */
+ if (PRIV (file_pos) < VMS_BLOCK_SIZE && room > 2)
+ room -= 2;
+ if (room < eisd->u.eisd.eisdsize + EISD__K_LENEND)
+ alpha_vms_file_position_block (abfd);
+
+ eisd->file_pos = PRIV (file_pos);
+ PRIV (file_pos) += eisd->u.eisd.eisdsize;
+
+ if (eisd->u.eisd.flags & EISD__M_FIXUPVEC)
+ bfd_putl64 (eisd->u.eisd.virt_addr, eihd.iafva);
+ }
+
+ if (first_eisd != NULL)
+ {
+ bfd_putl32 (first_eisd->file_pos, eihd.isdoff);
+ /* Real size of end of eisd marker. */
+ PRIV (file_pos) += EISD__K_LENEND;
+ }
+
+ bfd_putl32 (PRIV (file_pos), eihd.size);
+ bfd_putl32 ((PRIV (file_pos) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE,
+ eihd.hdrblkcnt);
+
+ /* Place sections. */
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ if (!(sec->flags & SEC_HAS_CONTENTS))
+ continue;
+
+ eisd = vms_section_data (sec)->eisd;
+
+ /* Align on a block. */
+ alpha_vms_file_position_block (abfd);
+ sec->filepos = PRIV (file_pos);
+
+ if (eisd != NULL)
+ eisd->u.eisd.vbn = (sec->filepos / VMS_BLOCK_SIZE) + 1;
+
+ PRIV (file_pos) += sec->size;
+ }
+
+ if (eihs != NULL && dst != NULL)
+ {
+ bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn);
+ bfd_putl32 (dst->size, eihs->dstsize);
+ }
+
+ /* Write EISD in hdr. */
+ for (eisd = first_eisd; eisd && eisd->file_pos < VMS_BLOCK_SIZE;
+ eisd = eisd->next)
+ alpha_vms_swap_eisd_out
+ (eisd, (struct vms_eisd *)((char *)&eihd + eisd->file_pos));
+
+ /* Write first block. */
+ if (bfd_bwrite (&eihd, sizeof (eihd), abfd) != sizeof (eihd))
+ return FALSE;
+
+ /* Write remaining eisd. */
+ if (eisd != NULL)
+ {
+ unsigned char blk[VMS_BLOCK_SIZE];
+ struct vms_internal_eisd_map *next_eisd;
+
+ memset (blk, 0xff, sizeof (blk));
+ while (eisd != NULL)
+ {
+ alpha_vms_swap_eisd_out
+ (eisd,
+ (struct vms_eisd *)(blk + (eisd->file_pos % VMS_BLOCK_SIZE)));
+
+ next_eisd = eisd->next;
+ if (next_eisd == NULL
+ || (next_eisd->file_pos / VMS_BLOCK_SIZE
+ != eisd->file_pos / VMS_BLOCK_SIZE))
+ {
+ if (bfd_bwrite (blk, sizeof (blk), abfd) != sizeof (blk))
+ return FALSE;
+
+ memset (blk, 0xff, sizeof (blk));
+ }
+ eisd = next_eisd;
+ }
+ }
+
+ /* Write sections. */
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ unsigned char blk[VMS_BLOCK_SIZE];
+ bfd_size_type len;
+
+ if (sec->size == 0 || !(sec->flags & SEC_HAS_CONTENTS))
+ continue;
+ if (bfd_bwrite (sec->contents, sec->size, abfd) != sec->size)
+ return FALSE;
+
+ /* Pad. */
+ len = VMS_BLOCK_SIZE - sec->size % VMS_BLOCK_SIZE;
+ if (len != VMS_BLOCK_SIZE)
+ {
+ memset (blk, 0, len);
+ if (bfd_bwrite (blk, len, abfd) != len)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+\f
+/* Object write. */
+
+/* This hash routine borrowed from GNU-EMACS, and strengthened
+ slightly. ERY. */
+
+static int
+hash_string (const char *ptr)
+{
+ const unsigned char *p = (unsigned char *) ptr;
+ const unsigned char *end = p + strlen (ptr);
+ unsigned char c;
+ int hash = 0;
+
+ while (p != end)
+ {
+ c = *p++;
+ hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
+ }
+ return hash;
+}
+
+/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
+
+static char *
+_bfd_vms_length_hash_symbol (bfd *abfd, const char *in, int maxlen)
+{
+ unsigned long result;
+ int in_len;
+ char *new_name;
+ const char *old_name;
+ int i;
+ static char outbuf[EOBJ__C_SYMSIZ + 1];
+ char *out = outbuf;
+
+#if VMS_DEBUG
+ vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
+#endif
+
+ if (maxlen > EOBJ__C_SYMSIZ)
+ maxlen = EOBJ__C_SYMSIZ;
+
+ /* Save this for later. */
+ new_name = out;
+
+ /* We may need to truncate the symbol, save the hash for later. */
+ in_len = strlen (in);
+
+ result = (in_len > maxlen) ? hash_string (in) : 0;
+
+ old_name = in;
+
+ /* Do the length checking. */
+ if (in_len <= maxlen)
+ i = in_len;
+ else
+ {
+ if (PRIV (flag_hash_long_names))
+ i = maxlen - 9;
+ else
+ i = maxlen;
+ }
+
+ strncpy (out, in, (size_t) i);
+ in += i;
+ out += i;
+
+ if ((in_len > maxlen)
+ && PRIV (flag_hash_long_names))
+ sprintf (out, "_%08lx", result);
+ else
+ *out = 0;
+
+#if VMS_DEBUG
+ vms_debug (4, "--> [%d]\"%s\"\n", (int)strlen (outbuf), outbuf);
+#endif
+
+ if (in_len > maxlen
+ && PRIV (flag_hash_long_names)
+ && PRIV (flag_show_after_trunc))
+ printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
+
+ return outbuf;
+}
+
+/* Write section and symbol directory of bfd abfd. Return FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_write_egsd (bfd *abfd)
+{
+ asection *section;
+ asymbol *symbol;
+ unsigned int symnum;
+ int last_index = -1;
+ char dummy_name[10];
+ char *sname;
+ flagword new_flags, old_flags;
+ int abs_section_index = 0;
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+ vms_debug2 ((2, "vms_write_gsd\n"));
+
+ /* Output sections. */
+ section = abfd->sections;
+ vms_debug2 ((3, "%d sections found\n", abfd->section_count));
+
+ /* Egsd is quadword aligned. */
+ _bfd_vms_output_alignment (recwr, 8);
+
+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
+ _bfd_vms_output_long (recwr, 0);
+
+ while (section != 0)
+ {
+ vms_debug2 ((3, "Section #%d %s, %d bytes\n",
+ section->index, section->name, (int)section->size));
+
+ /* 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 (recwr, 64) < 0)
+ {
+ _bfd_vms_output_end (abfd, recwr);
+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
+ _bfd_vms_output_long (recwr, 0);
+ }
+
+ /* Create dummy sections to keep consecutive indices. */
+ while (section->index - last_index > 1)
+ {
+ vms_debug2 ((3, "index %d, last %d\n", section->index, last_index));
+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
+ _bfd_vms_output_short (recwr, 0);
+ _bfd_vms_output_short (recwr, 0);
+ _bfd_vms_output_long (recwr, 0);
+ sprintf (dummy_name, ".DUMMY%02d", last_index);
+ _bfd_vms_output_counted (recwr, dummy_name);
+ _bfd_vms_output_end_subrec (recwr);
+ last_index++;
+ }
+
+ /* Don't know if this is necessary for the linker but for now it keeps
+ vms_slurp_gsd happy */
+ sname = (char *)section->name;
+ if (*sname == '.')
+ {
+ sname++;
+ if ((*sname == 't') && (strcmp (sname, "text") == 0))
+ sname = EVAX_CODE_NAME;
+ else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
+ sname = EVAX_DATA_NAME;
+ else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
+ sname = EVAX_BSS_NAME;
+ else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
+ sname = EVAX_LINK_NAME;
+ else if ((*sname == 'r') && (strcmp (sname, "rdata") == 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))
+ sname = EVAX_LOCAL_NAME;
+ }
+ else
+ sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ__C_SECSIZ);
+
+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
+ _bfd_vms_output_short (recwr, section->alignment_power & 0xff);
+
+ if (bfd_is_com_section (section))
+ new_flags = (EGPS__V_OVR | EGPS__V_REL | EGPS__V_GBL | EGPS__V_RD
+ | EGPS__V_WRT | EGPS__V_NOMOD | EGPS__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__V_WRT;
+
+ new_flags &= ~vms_section_data (section)->no_flags;
+ new_flags |= vms_section_data (section)->flags;
+
+ vms_debug2 ((3, "sec flags %x\n", section->flags));
+ vms_debug2 ((3, "new_flags %x, _raw_size %lu\n",
+ new_flags, (unsigned long)section->size));
+
+ _bfd_vms_output_short (recwr, new_flags);
+ _bfd_vms_output_long (recwr, (unsigned long) section->size);
+ _bfd_vms_output_counted (recwr, sname);
+ _bfd_vms_output_end_subrec (recwr);
+
+ last_index = section->index;
+done:
+ section = section->next;
+ }
+
+ /* Output symbols. */
+ vms_debug2 ((3, "%d symbols found\n", abfd->symcount));
+
+ bfd_set_start_address (abfd, (bfd_vma) -1);
+
+ for (symnum = 0; symnum < abfd->symcount; symnum++)
+ {
+ char *hash;
+
+ symbol = abfd->outsymbols[symnum];
+ if (*(symbol->name) == '_')
+ {
+ if (strcmp (symbol->name, "__main") == 0)
+ bfd_set_start_address (abfd, (bfd_vma)symbol->value);
+ }
+ old_flags = symbol->flags;
+
+ if (old_flags & BSF_FILE)
+ continue;
+
+ if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */
+ && !bfd_is_und_section (symbol->section) /* and not xref... */
+ && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */
+ && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
+ continue;
+
+ /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */
+ if (_bfd_vms_output_check (recwr, 80) < 0)
+ {
+ _bfd_vms_output_end (abfd, recwr);
+ _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
+ _bfd_vms_output_long (recwr, 0);
+ }
+
+ _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYM);
+
+ /* Data type, alignment. */
+ _bfd_vms_output_short (recwr, 0);
+
+ new_flags = 0;
+
+ if (old_flags & BSF_WEAK)
+ new_flags |= EGSY__V_WEAK;
+ if (bfd_is_com_section (symbol->section)) /* .comm */
+ new_flags |= (EGSY__V_WEAK | EGSY__V_COMM);
+
+ if (old_flags & BSF_FUNCTION)
+ {
+ new_flags |= EGSY__V_NORM;
+ new_flags |= EGSY__V_REL;
+ }
+ if (old_flags & BSF_GLOBAL)
+ {
+ new_flags |= EGSY__V_DEF;
+ if (!bfd_is_abs_section (symbol->section))
+ new_flags |= EGSY__V_REL;
+ }
+ _bfd_vms_output_short (recwr, new_flags);
+
+ if (old_flags & BSF_GLOBAL)
+ {
+ /* Symbol definition. */
+ bfd_vma code_address = 0;
+ unsigned long ca_psindx = 0;
+ unsigned long psindx;
+
+ if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
+ {
+ asymbol *sym;
+
+ sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
+ code_address = sym->value;
+ ca_psindx = sym->section->index;
+ }
+ if (bfd_is_abs_section (symbol->section))
+ psindx = abs_section_index;
+ else
+ psindx = symbol->section->index;
+
+ _bfd_vms_output_quad (recwr, symbol->value);
+ _bfd_vms_output_quad (recwr, code_address);
+ _bfd_vms_output_long (recwr, ca_psindx);
+ _bfd_vms_output_long (recwr, psindx);
+ }
+ hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ__C_SYMSIZ);
+ _bfd_vms_output_counted (recwr, hash);
+
+ _bfd_vms_output_end_subrec (recwr);
+
+ }
+
+ _bfd_vms_output_alignment (recwr, 8);
+ _bfd_vms_output_end (abfd, recwr);
+
+ return TRUE;
+}
+
+/* Write object header for bfd abfd. Return FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_write_ehdr (bfd *abfd)
+{
+ asymbol *symbol;
+ unsigned int symnum;
+ int had_case = 0;
+ int had_file = 0;
+ char version [256];
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+ vms_debug2 ((2, "vms_write_ehdr (%p)\n", abfd));
+
+ _bfd_vms_output_alignment (recwr, 2);
+
+ /* EMH. */
+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
+ _bfd_vms_output_short (recwr, EMH__C_MHD);
+ _bfd_vms_output_short (recwr, EOBJ__C_STRLVL);
+ _bfd_vms_output_long (recwr, 0);
+ _bfd_vms_output_long (recwr, 0);
+ _bfd_vms_output_long (recwr, MAX_OUTREC_SIZE);
+
+ /* Create module name from filename. */
+ if (bfd_get_filename (abfd) != 0)
+ {
+ char *module = vms_get_module_name (bfd_get_filename (abfd), TRUE);
+ _bfd_vms_output_counted (recwr, module);
+ free (module);
+ }
+ else
+ _bfd_vms_output_counted (recwr, "NONAME");
+
+ _bfd_vms_output_counted (recwr, BFD_VERSION_STRING);
+ _bfd_vms_output_dump (recwr, get_vms_time_string (), EMH_DATE_LENGTH);
+ _bfd_vms_output_fill (recwr, 0, EMH_DATE_LENGTH);
+ _bfd_vms_output_end (abfd, recwr);
+
+ /* LMN. */
+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
+ _bfd_vms_output_short (recwr, EMH__C_LNM);
+ snprintf (version, sizeof (version), "GAS BFD v%s", BFD_VERSION_STRING);
+ _bfd_vms_output_dump (recwr, (unsigned char *)version, strlen (version));
+ _bfd_vms_output_end (abfd, recwr);
+
+ /* SRC. */
+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
+ _bfd_vms_output_short (recwr, EMH__C_SRC);
+
+ for (symnum = 0; symnum < abfd->symcount; symnum++)
+ {
+ symbol = abfd->outsymbols[symnum];
+
+ if (symbol->flags & BSF_FILE)
+ {
+ if (CONST_STRNEQ ((char *)symbol->name, "<CASE:"))
+ {
+ PRIV (flag_hash_long_names) = symbol->name[6] - '0';
+ PRIV (flag_show_after_trunc) = symbol->name[7] - '0';
+
+ if (had_file)
+ break;
+ had_case = 1;
+ continue;
+ }
+
+ _bfd_vms_output_dump (recwr, (unsigned char *) symbol->name,
+ (int) strlen (symbol->name));
+ if (had_case)
+ break;
+ had_file = 1;
+ }
+ }
+
+ if (symnum == abfd->symcount)
+ _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("noname"));
+
+ _bfd_vms_output_end (abfd, recwr);
+
+ /* TTL. */
+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
+ _bfd_vms_output_short (recwr, EMH__C_TTL);
+ _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("TTL"));
+ _bfd_vms_output_end (abfd, recwr);
+
+ /* CPR. */
+ _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
+ _bfd_vms_output_short (recwr, EMH__C_CPR);
+ _bfd_vms_output_dump (recwr,
+ (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996",
+ 39);
+ _bfd_vms_output_end (abfd, recwr);
+
+ return TRUE;
+}
+
+/* Part 4.6, relocations. */
+
+\f
+/* WRITE ETIR SECTION
+
+ This is still under construction and therefore not documented. */
+
+/* Close the etir/etbt record. */
+
+static void
+end_etir_record (bfd * abfd)
+{
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+ _bfd_vms_output_end (abfd, recwr);
+}
+
+static void
+start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset)
+{
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+ if (section->name[0] == '.' && section->name[1] == 'v'
+ && !strcmp (section->name, ".vmsdebug"))
+ {
+ _bfd_vms_output_begin (recwr, EOBJ__C_ETBT);
+
+ if (offset == 0)
+ {
+ /* Push start offset. */
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
+ _bfd_vms_output_long (recwr, (unsigned long) 0);
+ _bfd_vms_output_end_subrec (recwr);
+
+ /* Set location. */
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_DFLOC);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ }
+ else
+ {
+ _bfd_vms_output_begin (recwr, EOBJ__C_ETIR);
+
+ if (offset == 0)
+ {
+ /* Push start offset. */
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ);
+ _bfd_vms_output_long (recwr, (unsigned long) section->index);
+ _bfd_vms_output_quad (recwr, offset);
+ _bfd_vms_output_end_subrec (recwr);
+
+ /* Start = pop (). */
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_SETRB);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ }
+}
+
+/* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual
+ address VADDR in section specified by SEC_INDEX and NAME. */
+
+static void
+sto_imm (bfd *abfd, asection *section,
+ bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr)
+{
+ bfd_size_type size;
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+#if VMS_DEBUG
+ _bfd_vms_debug (8, "sto_imm %d bytes\n", (int) ssize);
+ _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr);
+#endif
+
+ while (ssize > 0)
+ {
+ /* Try all the rest. */
+ size = ssize;
+
+ if (_bfd_vms_output_check (recwr, size) < 0)
+ {
+ /* Doesn't fit, split ! */
+ end_etir_record (abfd);
+
+ start_etir_or_etbt_record (abfd, section, vaddr);
+
+ size = _bfd_vms_output_check (recwr, 0); /* get max size */
+ if (size > ssize) /* more than what's left ? */
+ size = ssize;
+ }
+
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_IMM);
+ _bfd_vms_output_long (recwr, (unsigned long) (size));
+ _bfd_vms_output_dump (recwr, cptr, size);
+ _bfd_vms_output_end_subrec (recwr);
+
+#if VMS_DEBUG
+ _bfd_vms_debug (10, "dumped %d bytes\n", (int) size);
+ _bfd_hexdump (10, cptr, (int) size, (int) vaddr);
+#endif
+
+ vaddr += size;
+ cptr += size;
+ ssize -= size;
+ }
+}
+
+static void
+etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen)
+{
+ if (_bfd_vms_output_check (&PRIV (recwr), checklen) < 0)
+ {
+ /* Not enough room in this record. Close it and open a new one. */
+ end_etir_record (abfd);
+ start_etir_or_etbt_record (abfd, section, vaddr);
+ }
+}
+
+/* Return whether RELOC must be deferred till the end. */
+
+static bfd_boolean
+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 TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/* Write section contents for bfd abfd. Return FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
+{
+ asection *section;
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+ vms_debug2 ((2, "vms_write_tir (%p, %d)\n", abfd, objtype));
+
+ _bfd_vms_output_alignment (recwr, 4);
+
+ PRIV (vms_linkage_index) = 1;
+
+ for (section = abfd->sections; section; section = section->next)
+ {
+ vms_debug2 ((4, "writing %d. section '%s' (%d bytes)\n",
+ section->index, section->name, (int) (section->size)));
+
+ if (!(section->flags & SEC_HAS_CONTENTS)
+ || bfd_is_com_section (section))
+ continue;
+
+ if (!section->contents)
+ {
+ bfd_set_error (bfd_error_no_contents);
+ return FALSE;
+ }
+
+ start_etir_or_etbt_record (abfd, section, 0);
+
+ if (section->flags & SEC_RELOC)
+ {
+ bfd_vma curr_addr = 0;
+ unsigned char *curr_data = section->contents;
+ bfd_size_type size;
+ int pass2_needed = 0;
+ int pass2_in_progress = 0;
+ unsigned int irel;
+
+ if (section->reloc_count <= 0)
+ (*_bfd_error_handler)
+ (_("SEC_RELOC with no relocs in section %s"), section->name);
+
+#if VMS_DEBUG
+ else
+ {
+ int i = section->reloc_count;
+ arelent **rptr = section->orelocation;
+ _bfd_vms_debug (4, "%d relocations:\n", i);
+ while (i-- > 0)
+ {
+ _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, "
+ "addr %08lx, off %08lx, len %d: %s\n",
+ (*(*rptr)->sym_ptr_ptr)->name,
+ (*(*rptr)->sym_ptr_ptr)->section->name,
+ (long) (*(*rptr)->sym_ptr_ptr)->value,
+ (unsigned long)(*rptr)->address,
+ (unsigned long)(*rptr)->addend,
+ bfd_get_reloc_size ((*rptr)->howto),
+ ( *rptr)->howto->name);
+ rptr++;
+ }
+ }
+#endif
+
+ new_pass:
+ for (irel = 0; irel < section->reloc_count; irel++)
+ {
+ struct evax_private_udata_struct *udata;
+ arelent *rptr = section->orelocation [irel];
+ bfd_vma addr = rptr->address;
+ asymbol *sym = *rptr->sym_ptr_ptr;
+ asection *sec = sym->section;
+ bfd_boolean defer = defer_reloc_p (rptr);
+ unsigned int slen;
+ char *hash;
+
+ if (pass2_in_progress)
+ {
+ /* Non-deferred relocs have already been output. */
+ if (!defer)
+ continue;
+ }
+ else
+ {
+ /* Deferred relocs must be output at the very end. */
+ if (defer)
+ {
+ pass2_needed = 1;
+ continue;
+ }
+
+ /* Regular relocs are intertwined with binary data. */
+ if (curr_addr > addr)
+ (*_bfd_error_handler) (_("Size error in section %s"),
+ section->name);
+ size = addr - curr_addr;
+ sto_imm (abfd, section, size, curr_data, curr_addr);
+ curr_data += size;
+ curr_addr += size;
+ }
+
+ size = bfd_get_reloc_size (rptr->howto);
+
+ switch (rptr->howto->type)
+ {
+ case ALPHA_R_IGNORE:
+ break;
+
+ case ALPHA_R_REFLONG:
+ if (bfd_is_und_section (sym->section))
+ {
+ bfd_vma addend = rptr->addend;
+ slen = strlen ((char *) sym->name);
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ__C_SYMSIZ);
+ etir_output_check (abfd, section, curr_addr, slen);
+ if (addend)
+ {
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL);
+ _bfd_vms_output_counted (recwr, hash);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
+ _bfd_vms_output_long (recwr, (unsigned long) addend);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ else
+ {
+ _bfd_vms_output_begin_subrec
+ (recwr, ETIR__C_STO_GBL_LW);
+ _bfd_vms_output_counted (recwr, hash);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ }
+ else if (bfd_is_abs_section (sym->section))
+ {
+ etir_output_check (abfd, section, curr_addr, 16);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
+ _bfd_vms_output_long (recwr, (unsigned long) sym->value);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ else
+ {
+ etir_output_check (abfd, section, curr_addr, 32);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ);
+ _bfd_vms_output_long (recwr, (unsigned long) sec->index);
+ _bfd_vms_output_quad (recwr, rptr->addend + sym->value);
+ _bfd_vms_output_end_subrec (recwr);
+ /* ??? Table B-8 of the OpenVMS Linker Utilily Manual
+ says that we should have a ETIR__C_STO_OFF here.
+ But the relocation would not be BFD_RELOC_32 then.
+ This case is very likely unreachable. */
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ break;
+
+ case ALPHA_R_REFQUAD:
+ if (bfd_is_und_section (sym->section))
+ {
+ bfd_vma addend = rptr->addend;
+ slen = strlen ((char *) sym->name);
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ__C_SYMSIZ);
+ etir_output_check (abfd, section, curr_addr, slen);
+ if (addend)
+ {
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL);
+ _bfd_vms_output_counted (recwr, hash);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW);
+ _bfd_vms_output_quad (recwr, addend);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ else
+ {
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL);
+ _bfd_vms_output_counted (recwr, hash);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ }
+ else if (bfd_is_abs_section (sym->section))
+ {
+ etir_output_check (abfd, section, curr_addr, 16);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW);
+ _bfd_vms_output_quad (recwr, sym->value);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ else
+ {
+ etir_output_check (abfd, section, curr_addr, 32);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ);
+ _bfd_vms_output_long (recwr, (unsigned long) sec->index);
+ _bfd_vms_output_quad (recwr, rptr->addend + sym->value);
+ _bfd_vms_output_end_subrec (recwr);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_OFF);
+ _bfd_vms_output_end_subrec (recwr);
+ }
+ break;
+
+ case ALPHA_R_HINT:
+ sto_imm (abfd, section, size, curr_data, curr_addr);
+ break;
+
+ case ALPHA_R_LINKAGE:
+ etir_output_check (abfd, section, curr_addr, 64);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LP_PSB);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) PRIV (vms_linkage_index));
+ PRIV (vms_linkage_index) += 2;
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ__C_SYMSIZ);
+ _bfd_vms_output_counted (recwr, hash);
+ _bfd_vms_output_byte (recwr, 0);
+ _bfd_vms_output_end_subrec (recwr);
+ break;
+
+ case ALPHA_R_CODEADDR:
+ slen = strlen ((char *) sym->name);
+ hash = _bfd_vms_length_hash_symbol
+ (abfd, sym->name, EOBJ__C_SYMSIZ);
+ etir_output_check (abfd, section, curr_addr, slen);
+ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_CA);
+ _bfd_vms_output_counted (recwr, hash);
+ _bfd_vms_output_end_subrec (recwr);
+ 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_subrec (recwr, ETIR__C_STC_NOP_GBL);
+ _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (recwr, rptr->address);
+ _bfd_vms_output_long (recwr, (unsigned long) 0x47ff041f);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (recwr, rptr->addend);
+ _bfd_vms_output_counted
+ (recwr, _bfd_vms_length_hash_symbol
+ (abfd, udata->origname, EOBJ__C_SYMSIZ));
+ _bfd_vms_output_end_subrec (recwr);
+ 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_subrec (recwr, ETIR__C_STC_LDA_GBL);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->lkindex + 1);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (recwr, rptr->address);
+ _bfd_vms_output_long (recwr, (unsigned long) 0x237B0000);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->bsym->section->index);
+ _bfd_vms_output_quad (recwr, rptr->addend);
+ _bfd_vms_output_counted
+ (recwr, _bfd_vms_length_hash_symbol
+ (abfd, udata->origname, EOBJ__C_SYMSIZ));
+ _bfd_vms_output_end_subrec (recwr);
+ 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_subrec (recwr, ETIR__C_STC_BOH_GBL);
+ _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (recwr, rptr->address);
+ _bfd_vms_output_long (recwr, (unsigned long) 0xD3400000);
+ _bfd_vms_output_long
+ (recwr, (unsigned long) udata->enbsym->section->index);
+ _bfd_vms_output_quad (recwr, rptr->addend);
+ _bfd_vms_output_counted
+ (recwr, _bfd_vms_length_hash_symbol
+ (abfd, udata->origname, EOBJ__C_SYMSIZ));
+ _bfd_vms_output_end_subrec (recwr);
+ break;
+
+ default:
+ (*_bfd_error_handler) (_("Unhandled relocation %s"),
+ rptr->howto->name);
+ break;
+ }
+
+ curr_data += size;
+ curr_addr += size;
+ } /* End of relocs loop. */
+
+ if (!pass2_in_progress)
+ {
+ /* Output rest of section. */
+ if (curr_addr > section->size)
+ (*_bfd_error_handler) (_("Size error in section %s"),
+ section->name);
+ size = section->size - curr_addr;
+ sto_imm (abfd, section, size, curr_data, curr_addr);
+ curr_data += size;
+ curr_addr += size;
+
+ if (pass2_needed)
+ {
+ pass2_in_progress = 1;
+ goto new_pass;
+ }
+ }
+ }
+
+ else /* (section->flags & SEC_RELOC) */
+ sto_imm (abfd, section, section->size, section->contents, 0);
+
+ end_etir_record (abfd);
+ }
+
+ _bfd_vms_output_alignment (recwr, 2);
+ return TRUE;
+}
+
+/* Write eom record for bfd abfd. Return FALSE on error. */
+
+static bfd_boolean
+_bfd_vms_write_eeom (bfd *abfd)
+{
+ struct vms_rec_wr *recwr = &PRIV (recwr);
+
+ vms_debug2 ((2, "vms_write_eeom\n"));
+
+ _bfd_vms_output_begin (recwr, EOBJ__C_EEOM);
+ _bfd_vms_output_long (recwr, (unsigned long) (PRIV (vms_linkage_index) >> 1));
+ _bfd_vms_output_byte (recwr, 0); /* Completion code. */
+ _bfd_vms_output_byte (recwr, 0); /* Fill byte. */
+
+ if (bfd_get_start_address (abfd) != (bfd_vma)-1)
+ {
+ asection *section;
+
+ section = bfd_get_section_by_name (abfd, ".link");
+ if (section == 0)
+ {
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return FALSE;
+ }
+ _bfd_vms_output_short (recwr, 0);
+ _bfd_vms_output_long (recwr, (unsigned long) (section->index));
+ _bfd_vms_output_long (recwr,
+ (unsigned long) bfd_get_start_address (abfd));
+ _bfd_vms_output_long (recwr, 0);
+ }
+
+ _bfd_vms_output_end (abfd, recwr);
+ return TRUE;
+}
+
+/* Write cached information into a file being written, at bfd_close. */
+
+static bfd_boolean
+alpha_vms_write_object_contents (bfd *abfd)
+{
+ vms_debug2 ((1, "vms_write_object_contents (%p)\n", abfd));
+
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ {
+ return alpha_vms_write_exec (abfd);
+ }
+ else
+ {
+ if (abfd->section_count > 0) /* we have sections */
+ {
+ if (_bfd_vms_write_ehdr (abfd) != TRUE)
+ return FALSE;
+ if (_bfd_vms_write_egsd (abfd) != TRUE)
+ return FALSE;
+ if (_bfd_vms_write_etir (abfd, EOBJ__C_ETIR) != TRUE)
+ return FALSE;
+ if (_bfd_vms_write_eeom (abfd) != TRUE)
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+\f
+/* Debug stuff: nearest line. */
+
+#define SET_MODULE_PARSED(m) \
+ do { if ((m)->name == NULL) (m)->name = ""; } while (0)
+#define IS_MODULE_PARSED(m) ((m)->name != NULL)
+
+/* 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,
+ int length)
+{
+ unsigned char *maxptr = ptr + length;
+ unsigned char *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 (length == -1 || 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);
+
+ vms_debug2 ((2, "DST record: leng %d, type %d\n", rec_length, rec_type));
+
+ if (length == -1 && rec_type == DST__K_MODEND)
+ break;
+
+ switch (rec_type)
+ {
+ case DST__K_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;
+
+ vms_debug2 ((3, "module: %s\n", module->name));
+ break;
+
+ case DST__K_MODEND:
+ break;
+
+ case DST__K_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;
+
+ vms_debug2 ((3, "routine: %s at 0x%lx\n",
+ funcinfo->name, (unsigned long) funcinfo->low));
+ break;
+
+ case DST__K_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;
+
+ vms_debug2 ((3, "end routine\n"));
+ break;
+
+ case DST__K_PROLOG:
+ vms_debug2 ((3, "prologue\n"));
+ break;
+
+ case DST__K_EPILOG:
+ vms_debug2 ((3, "epilog\n"));
+ break;
+
+ case DST__K_BLKBEG:
+ vms_debug2 ((3, "block\n"));
+ break;
+
+ case DST__K_BLKEND:
+ vms_debug2 ((3, "end block\n"));
+ break;
+
+ case DST__K_SOURCE:
+ src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE;
+
+ vms_debug2 ((3, "source info\n"));
+
+ while (src_ptr < ptr + rec_length)
+ {
+ int cmd = src_ptr[0], cmd_length, data;
+
+ switch (cmd)
+ {
+ case DST__K_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;
+ vms_debug2 ((4, "DST_S_C_SRC_DECLFILE: %d, %s\n",
+ fileid, module->file_table [fileid].name));
+ }
+ break;
+
+ case DST__K_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;
+ vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_B: %d\n", data));
+ break;
+
+ case DST__K_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;
+ vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_W: %d\n", data));
+ break;
+
+ case DST__K_SRC_INCRLNUM_B:
+ data = src_ptr[DST_S_B_SRC_UNSBYTE];
+ curr_srec->line += data;
+ cmd_length = 2;
+ vms_debug2 ((4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data));
+ break;
+
+ case DST__K_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;
+ vms_debug2 ((4, "DST_S_C_SRC_SETFILE: %d\n", data));
+ break;
+
+ case DST__K_SRC_SETLNUM_L:
+ data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
+ curr_srec->line = data;
+ cmd_length = 5;
+ vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_L: %d\n", data));
+ break;
+
+ case DST__K_SRC_SETLNUM_W:
+ data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
+ curr_srec->line = data;
+ cmd_length = 3;
+ vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_W: %d\n", data));
+ break;
+
+ case DST__K_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;
+ vms_debug2 ((4, "DST_S_C_SRC_SETREC_L: %d\n", data));
+ break;
+
+ case DST__K_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;
+ vms_debug2 ((4, "DST_S_C_SRC_SETREC_W: %d\n", data));
+ break;
+
+ case DST__K_SRC_FORMFEED:
+ cmd_length = 1;
+ vms_debug2 ((4, "DST_S_C_SRC_FORMFEED\n"));
+ break;
+
+ default:
+ (*_bfd_error_handler) (_("unknown source command %d"),
+ cmd);
+ cmd_length = 2;
+ break;
+ }
+
+ src_ptr += cmd_length;
+ }
+ break;
+
+ case DST__K_LINE_NUM:
+ pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE;
+
+ vms_debug2 ((3, "line info\n"));
+
+ 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__K_DELTA_PC_W:
+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
+ curr_pc += data;
+ curr_linenum += 1;
+ cmd_length = 3;
+ vms_debug2 ((4, "DST__K_DELTA_PC_W: %d\n", data));
+ break;
+
+ case DST__K_DELTA_PC_L:
+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
+ curr_pc += data;
+ curr_linenum += 1;
+ cmd_length = 5;
+ vms_debug2 ((4, "DST__K_DELTA_PC_L: %d\n", data));
+ break;
+
+ case DST__K_INCR_LINUM:
+ data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
+ curr_linenum += data;
+ cmd_length = 2;
+ vms_debug2 ((4, "DST__K_INCR_LINUM: %d\n", data));
+ break;
+
+ case DST__K_INCR_LINUM_W:
+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
+ curr_linenum += data;
+ cmd_length = 3;
+ vms_debug2 ((4, "DST__K_INCR_LINUM_W: %d\n", data));
+ break;
+
+ case DST__K_INCR_LINUM_L:
+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
+ curr_linenum += data;
+ cmd_length = 5;
+ vms_debug2 ((4, "DST__K_INCR_LINUM_L: %d\n", data));
+ break;
+
+ case DST__K_SET_LINUM_INCR:
+ (*_bfd_error_handler)
+ (_("DST__K_SET_LINUM_INCR not implemented"));
+ cmd_length = 2;
+ break;
+
+ case DST__K_SET_LINUM_INCR_W:
+ (*_bfd_error_handler)
+ (_("DST__K_SET_LINUM_INCR_W not implemented"));
+ cmd_length = 3;
+ break;
+
+ case DST__K_RESET_LINUM_INCR:
+ (*_bfd_error_handler)
+ (_("DST__K_RESET_LINUM_INCR not implemented"));
+ cmd_length = 1;
+ break;
+
+ case DST__K_BEG_STMT_MODE:
+ (*_bfd_error_handler)
+ (_("DST__K_BEG_STMT_MODE not implemented"));
+ cmd_length = 1;
+ break;
+
+ case DST__K_END_STMT_MODE:
+ (*_bfd_error_handler)
+ (_("DST__K_END_STMT_MODE not implemented"));
+ cmd_length = 1;
+ break;
+
+ case DST__K_SET_LINUM_B:
+ data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
+ curr_linenum = data;
+ cmd_length = 2;
+ vms_debug2 ((4, "DST__K_SET_LINUM_B: %d\n", data));
+ break;
+
+ case DST__K_SET_LINUM:
+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
+ curr_linenum = data;
+ cmd_length = 3;
+ vms_debug2 ((4, "DST__K_SET_LINE_NUM: %d\n", data));
+ break;
+
+ case DST__K_SET_LINUM_L:
+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
+ curr_linenum = data;
+ cmd_length = 5;
+ vms_debug2 ((4, "DST__K_SET_LINUM_L: %d\n", data));
+ break;
+
+ case DST__K_SET_PC:
+ (*_bfd_error_handler)
+ (_("DST__K_SET_PC not implemented"));
+ cmd_length = 2;
+ break;
+
+ case DST__K_SET_PC_W:
+ (*_bfd_error_handler)
+ (_("DST__K_SET_PC_W not implemented"));
+ cmd_length = 3;
+ break;
+
+ case DST__K_SET_PC_L:
+ (*_bfd_error_handler)
+ (_("DST__K_SET_PC_L not implemented"));
+ cmd_length = 5;
+ break;
+
+ case DST__K_SET_STMTNUM:
+ (*_bfd_error_handler)
+ (_("DST__K_SET_STMTNUM not implemented"));
+ cmd_length = 2;
+ break;
+
+ case DST__K_TERM:
+ data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
+ curr_pc += data;
+ cmd_length = 2;
+ vms_debug2 ((4, "DST__K_TERM: %d\n", data));
+ break;
+
+ case DST__K_TERM_W:
+ data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
+ curr_pc += data;
+ cmd_length = 3;
+ vms_debug2 ((4, "DST__K_TERM_W: %d\n", data));
+ break;
+
+ case DST__K_TERM_L:
+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
+ curr_pc += data;
+ cmd_length = 5;
+ vms_debug2 ((4, "DST__K_TERM_L: %d\n", data));
+ break;
+
+ case DST__K_SET_ABS_PC:
+ data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
+ curr_pc = data;
+ cmd_length = 5;
+ vms_debug2 ((4, "DST__K_SET_ABS_PC: 0x%x\n", data));
+ break;
+
+ default:
+ if (cmd <= 0)
+ {
+ curr_pc -= cmd;
+ curr_linenum += 1;
+ cmd_length = 1;
+ vms_debug2 ((4, "bump pc to 0x%lx and line to %d\n",
+ (unsigned long)curr_pc, curr_linenum));
+ }
+ 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__K_DELTA_PC_L
+ || cmd == DST__K_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;
+ vms_debug2 ((4, "-> correlate pc 0x%lx with line %d\n",
+ (unsigned long)curr_pc, curr_linenum));
+ }
+
+ pcl_ptr += cmd_length;
+ }
+ break;
+
+ case 0x17: /* Undocumented type used by DEC C to declare equates. */
+ vms_debug2 ((3, "undocumented type 0x17\n"));
+ break;
+
+ default:
+ vms_debug2 ((3, "ignoring record\n"));
+ 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;
+
+ vms_debug2 ((2, "DMT\n"));
+
+ 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 msize = 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;
+
+ vms_debug2 ((3, "module: modbeg = %d, size = %d, count = %d\n",
+ modbeg, msize, count));
+
+ /* 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 = msize;
+ module->low = start;
+ module->high = start + length;
+ module->next = list;
+ list = module;
+ ptr += DBG_S_C_DMT_PSECT_SIZE;
+
+ vms_debug2 ((4, "section: start = 0x%x, length = %d\n",
+ start, length));
+ }
+ }
+ }
+ 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, -1);
+ 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. */
+
+static 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 || !(abfd->flags & (EXEC_P | DYNAMIC)))
+ 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;
+}
+\f
+/* Canonicalizations. */
+/* Set name, value, section and flags of SYM from E. */
+
+static bfd_boolean
+alpha_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym)
+{
+ flagword flags;
+ symvalue value;
+ asection *sec;
+ const char *name;
+
+ name = e->name;
+ value = 0;
+ flags = BSF_NO_FLAGS;
+ sec = NULL;
+
+ switch (e->typ)
+ {
+ case EGSD__C_SYM:
+ if (e->flags & EGSY__V_WEAK)
+ flags |= BSF_WEAK;
+
+ if (e->flags & EGSY__V_DEF)
+ {
+ /* Symbol definition. */
+ flags |= BSF_GLOBAL;
+ if (e->flags & EGSY__V_NORM)
+ flags |= BSF_FUNCTION;
+ value = e->value;
+ sec = PRIV (sections)[e->section];
+ }
+ else
+ {
+ /* Symbol reference. */
+ sec = bfd_und_section_ptr;
+ }
+ break;
+
+ case EGSD__C_SYMG:
+ /* A universal symbol is by definition global... */
+ flags |= BSF_GLOBAL;
+
+ /* ...and dynamic in shared libraries. */
+ if (abfd->flags & DYNAMIC)
+ flags |= BSF_DYNAMIC;
+
+ if (e->flags & EGSY__V_WEAK)
+ flags |= BSF_WEAK;
+
+ if (!(e->flags & EGSY__V_DEF))
+ abort ();
+
+ if (e->flags & EGSY__V_NORM)
+ flags |= BSF_FUNCTION;
+
+ value = e->symbol_vector;
+
+ /* Adding this offset is necessary in order for GDB to
+ read the DWARF-2 debug info from shared libraries. */
+ if ((abfd->flags & DYNAMIC) && strstr (name, "$DWARF2.DEBUG") != 0)
+ value += PRIV (symvva);
+
+ sec = bfd_abs_section_ptr;
+#if 0
+ /* Find containing section. */
+ {
+ bfd_vma sbase = 0;
+ asection *s;
+
+ for (s = abfd->sections; s; s = s->next)
+ {
+ if (value >= s->vma
+ && s->vma > sbase
+ && !(s->flags & SEC_COFF_SHARED_LIBRARY)
+ && (s->size > 0 || !(e->flags & EGSY__V_REL)))
+ {
+ sbase = s->vma;
+ sec = s;
+ }
+ }
+ value -= sbase;
+ }
+#endif
+
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ sym->name = name;
+ sym->section = sec;
+ sym->flags = flags;
+ sym->value = value;
+ return TRUE;
+}
+
+
+/* Return the number of bytes required to store a vector of pointers
+ to asymbols for all the symbols in the BFD abfd, including a
+ terminal NULL pointer. If there are no symbols in the BFD,
+ then return 0. If an error occurs, return -1. */
+
+static long
+alpha_vms_get_symtab_upper_bound (bfd *abfd)
+{
+ vms_debug2 ((1, "alpha_vms_get_symtab_upper_bound (%p), %d symbols\n",
+ abfd, PRIV (gsd_sym_count)));
+
+ return (PRIV (gsd_sym_count) + 1) * sizeof (asymbol *);
+}
+
+/* Read the symbols from the BFD abfd, and fills in the vector
+ location with pointers to the symbols and a trailing NULL.
+
+ Return number of symbols read. */
+
+static long
+alpha_vms_canonicalize_symtab (bfd *abfd, asymbol **symbols)
+{
+ unsigned int i;
+
+ vms_debug2 ((1, "alpha_vms_canonicalize_symtab (%p, <ret>)\n", abfd));
+
+ if (PRIV (csymbols) == NULL)
+ {
+ PRIV (csymbols) = (asymbol **) bfd_alloc
+ (abfd, PRIV (gsd_sym_count) * sizeof (asymbol *));
+
+ /* Traverse table and fill symbols vector. */
+ for (i = 0; i < PRIV (gsd_sym_count); i++)
+ {
+ struct vms_symbol_entry *e = PRIV (syms)[i];
+ asymbol *sym;
+
+ sym = bfd_make_empty_symbol (abfd);
+ if (sym == NULL || !alpha_vms_convert_symbol (abfd, e, sym))
+ {
+ bfd_release (abfd, PRIV (csymbols));
+ PRIV (csymbols) = NULL;
+ return -1;
+ }
+
+ PRIV (csymbols)[i] = sym;
+ }
+ }
+
+ if (symbols != NULL)
+ {
+ for (i = 0; i < PRIV (gsd_sym_count); i++)
+ symbols[i] = PRIV (csymbols)[i];
+ symbols[i] = NULL;
+ }
+
+ return PRIV (gsd_sym_count);
+}
+
+/* Read and convert relocations from ETIR. We do it once for all sections. */
+
+static bfd_boolean
+alpha_vms_slurp_relocs (bfd *abfd)
+{
+ int cur_psect = -1;
+
+ vms_debug2 ((3, "alpha_vms_slurp_relocs\n"));
+
+ /* We slurp relocs only once, for all sections. */
+ if (PRIV (reloc_done))
+ return TRUE;
+ PRIV (reloc_done) = TRUE;
+
+ if (alpha_vms_canonicalize_symtab (abfd, NULL) < 0)
+ return FALSE;
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ return FALSE;
+
+ while (1)
+ {
+ unsigned char *begin;
+ unsigned char *end;
+ unsigned char *ptr;
+ bfd_reloc_code_real_type reloc_code;
+ int type;
+ bfd_vma vaddr = 0;
+
+ int length;
+
+ bfd_vma cur_address;
+ int cur_psidx = -1;
+ unsigned char *cur_sym = NULL;
+ int prev_cmd = -1;
+ bfd_vma cur_addend = 0;
+
+ /* Skip non-ETIR records. */
+ type = _bfd_vms_get_object_record (abfd);
+ if (type == EOBJ__C_EEOM)
+ break;
+ if (type != EOBJ__C_ETIR)
+ continue;
+
+ begin = PRIV (recrd.rec) + 4;
+ end = PRIV (recrd.rec) + PRIV (recrd.rec_size);
+
+ for (ptr = begin; ptr < end; ptr += length)
+ {
+ int cmd;
+
+ cmd = bfd_getl16 (ptr);
+ length = bfd_getl16 (ptr + 2);
+
+ cur_address = vaddr;
+
+ vms_debug2 ((4, "alpha_vms_slurp_relocs: etir %s\n",
+ _bfd_vms_etir_name (cmd)));
+
+ switch (cmd)
+ {
+ case ETIR__C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */
+ /* ALPHA_R_REFQUAD und_section, step 1 */
+ cur_sym = ptr + 4;
+ prev_cmd = cmd;
+ continue;
+
+ case ETIR__C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */
+ cur_psidx = bfd_getl32 (ptr + 4);
+ cur_addend = bfd_getl64 (ptr + 8);
+ prev_cmd = cmd;
+ continue;
+
+ case ETIR__C_CTL_SETRB:
+ if (prev_cmd != ETIR__C_STA_PQ)
+ {
+ (*_bfd_error_handler)
+ (_("Unknown reloc %s + %s"), _bfd_vms_etir_name (prev_cmd),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ }
+ cur_psect = cur_psidx;
+ vaddr = cur_addend;
+ cur_psidx = -1;
+ cur_addend = 0;
+ continue;
+
+ case ETIR__C_STA_LW: /* ALPHA_R_REFLONG abs_section, step 1 */
+ /* ALPHA_R_REFLONG und_section, step 2 */
+ if (prev_cmd != -1)
+ {
+ if (prev_cmd != ETIR__C_STA_GBL)
+ {
+ (*_bfd_error_handler)
+ (_("Unknown reloc %s + %s"), _bfd_vms_etir_name (cmd),
+ _bfd_vms_etir_name (ETIR__C_STA_LW));
+ return FALSE;
+ }
+ }
+ cur_addend = bfd_getl32 (ptr + 4);
+ prev_cmd = cmd;
+ continue;
+
+ case ETIR__C_STA_QW: /* ALPHA_R_REFQUAD abs_section, step 1 */
+ /* ALPHA_R_REFQUAD und_section, step 2 */
+ if (prev_cmd != -1 && prev_cmd != ETIR__C_STA_GBL)
+ {
+ (*_bfd_error_handler)
+ (_("Unknown reloc %s + %s"), _bfd_vms_etir_name (cmd),
+ _bfd_vms_etir_name (ETIR__C_STA_QW));
+ return FALSE;
+ }
+ cur_addend = bfd_getl64 (ptr + 4);
+ prev_cmd = cmd;
+ continue;
+
+ case ETIR__C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */
+ /* ALPHA_R_REFLONG abs_section, step 2 */
+ /* ALPHA_R_REFLONG others, step 2 */
+ if (prev_cmd != ETIR__C_OPR_ADD
+ && prev_cmd != ETIR__C_STA_LW
+ && prev_cmd != ETIR__C_STA_PQ)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ _bfd_vms_etir_name (prev_cmd),
+ _bfd_vms_etir_name (ETIR__C_STO_LW));
+ return FALSE;
+ }
+ reloc_code = BFD_RELOC_32;
+ break;
+
+ case ETIR__C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */
+ /* ALPHA_R_REFQUAD abs_section, step 2 */
+ if (prev_cmd != ETIR__C_OPR_ADD && prev_cmd != ETIR__C_STA_QW)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ _bfd_vms_etir_name (prev_cmd),
+ _bfd_vms_etir_name (ETIR__C_STO_QW));
+ return FALSE;
+ }
+ reloc_code = BFD_RELOC_64;
+ break;
+
+ case ETIR__C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */
+ if (prev_cmd != ETIR__C_STA_PQ)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ _bfd_vms_etir_name (prev_cmd),
+ _bfd_vms_etir_name (ETIR__C_STO_OFF));
+ return FALSE;
+ }
+ reloc_code = BFD_RELOC_64;
+ break;
+
+ case ETIR__C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */
+ /* ALPHA_R_REFQUAD und_section, step 3 */
+ if (prev_cmd != ETIR__C_STA_LW && prev_cmd != ETIR__C_STA_QW)
+ {
+ (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
+ _bfd_vms_etir_name (prev_cmd),
+ _bfd_vms_etir_name (ETIR__C_OPR_ADD));
+ return FALSE;
+ }
+ prev_cmd = ETIR__C_OPR_ADD;
+ continue;
+
+ case ETIR__C_STO_CA: /* ALPHA_R_CODEADDR */
+ reloc_code = BFD_RELOC_ALPHA_CODEADDR;
+ cur_sym = ptr + 4;
+ break;
+
+ case ETIR__C_STO_GBL: /* ALPHA_R_REFQUAD und_section */
+ reloc_code = BFD_RELOC_64;
+ cur_sym = ptr + 4;
+ break;
+
+ case ETIR__C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */
+ reloc_code = BFD_RELOC_32;
+ cur_sym = ptr + 4;
+ break;
+
+ case ETIR__C_STC_LP_PSB: /* ALPHA_R_LINKAGE */
+ reloc_code = BFD_RELOC_ALPHA_LINKAGE;
+ cur_sym = ptr + 8;
+ break;
+
+ case ETIR__C_STC_NOP_GBL: /* ALPHA_R_NOP */
+ reloc_code = BFD_RELOC_ALPHA_NOP;
+ goto call_reloc;
+
+ case ETIR__C_STC_BSR_GBL: /* ALPHA_R_BSR */
+ reloc_code = BFD_RELOC_ALPHA_BSR;
+ goto call_reloc;
+
+ case ETIR__C_STC_LDA_GBL: /* ALPHA_R_LDA */
+ reloc_code = BFD_RELOC_ALPHA_LDA;
+ goto call_reloc;
+
+ case ETIR__C_STC_BOH_GBL: /* ALPHA_R_BOH */
+ reloc_code = BFD_RELOC_ALPHA_BOH;
+ goto call_reloc;
+
+ call_reloc:
+ cur_sym = ptr + 4 + 32;
+ cur_address = bfd_getl64 (ptr + 4 + 8);
+ cur_addend = bfd_getl64 (ptr + 4 + 24);
+ break;
+
+ case ETIR__C_STO_IMM:
+ vaddr += bfd_getl32 (ptr + 4);
+ continue;
+
+ default:
+ (*_bfd_error_handler) (_("Unknown reloc %s"),
+ _bfd_vms_etir_name (cmd));
+ return FALSE;
+ }
+
+ {
+ asection *sec;
+ struct vms_section_data_struct *vms_sec;
+ arelent *reloc;
+
+ /* Get section to which the relocation applies. */
+ if (cur_psect < 0 || cur_psect > (int)PRIV (section_count))
+ {
+ (*_bfd_error_handler) (_("Invalid section index in ETIR"));
+ return FALSE;
+ }
+ sec = PRIV (sections)[cur_psect];
+ vms_sec = vms_section_data (sec);
+
+ /* Allocate a reloc entry. */
+ if (sec->reloc_count >= vms_sec->reloc_max)
+ {
+ if (vms_sec->reloc_max == 0)
+ {
+ vms_sec->reloc_max = 64;
+ sec->relocation = bfd_zmalloc
+ (vms_sec->reloc_max * sizeof (arelent));
+ }
+ else
+ {
+ vms_sec->reloc_max *= 2;
+ sec->relocation = bfd_realloc
+ (sec->relocation, vms_sec->reloc_max * sizeof (arelent));
+ }
+ }
+ reloc = &sec->relocation[sec->reloc_count];
+ sec->reloc_count++;
+
+ reloc->howto = bfd_reloc_type_lookup (abfd, reloc_code);
+
+ if (cur_sym != NULL)
+ {
+ unsigned int j;
+ unsigned int symlen = *cur_sym;
+ asymbol **sym;
+
+ /* Linear search. */
+ symlen = *cur_sym;
+ cur_sym++;
+ sym = NULL;
+
+ for (j = 0; j < PRIV (gsd_sym_count); j++)
+ if (PRIV (syms)[j]->namelen == symlen
+ && memcmp (PRIV (syms)[j]->name, cur_sym, symlen) == 0)
+ {
+ sym = &PRIV (csymbols)[j];
+ break;
+ }
+ if (sym == NULL)
+ {
+ (*_bfd_error_handler) (_("Unknown symbol in command %s"),
+ _bfd_vms_etir_name (cmd));
+ reloc->sym_ptr_ptr = NULL;
+ }
+ else
+ reloc->sym_ptr_ptr = sym;
+ }
+ else if (cur_psidx >= 0)
+ reloc->sym_ptr_ptr =
+ PRIV (sections)[cur_psidx]->symbol_ptr_ptr;
+ else
+ reloc->sym_ptr_ptr = NULL;
+
+ reloc->address = cur_address;
+ reloc->addend = cur_addend;
+
+ vaddr += bfd_get_reloc_size (reloc->howto);
+ }
+
+ cur_addend = 0;
+ prev_cmd = -1;
+ cur_sym = NULL;
+ cur_psidx = -1;
+ }
+ }
+ vms_debug2 ((3, "alpha_vms_slurp_relocs: result = TRUE\n"));
+
+ return TRUE;
+}
+
+/* Return the number of bytes required to store the relocation
+ information associated with the given section. */
+
+static long
+alpha_vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
+{
+ alpha_vms_slurp_relocs (abfd);
+
+ return (section->reloc_count + 1) * sizeof (arelent *);
+}
+
+/* Convert relocations from VMS (external) form into BFD internal
+ form. Return the number of relocations. */
+
+static long
+alpha_vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr,
+ asymbol **symbols ATTRIBUTE_UNUSED)
+{
+ arelent *tblptr;
+ int count;
+
+ if (!alpha_vms_slurp_relocs (abfd))
+ 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. */
+
+/* How to process the various reloc types. */
+
+static bfd_reloc_status_type
+reloc_nil (bfd * abfd ATTRIBUTE_UNUSED,
+ arelent *reloc ATTRIBUTE_UNUSED,
+ asymbol *sym ATTRIBUTE_UNUSED,
+ void * data ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ bfd *output_bfd ATTRIBUTE_UNUSED,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+#if VMS_DEBUG
+ vms_debug (1, "reloc_nil (abfd %p, output_bfd %p)\n", abfd, output_bfd);
+ vms_debug (2, "In section %s, symbol %s\n",
+ sec->name, sym->name);
+ vms_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n",
+ reloc->sym_ptr_ptr[0]->name,
+ (unsigned long)reloc->address,
+ (unsigned long)reloc->addend, reloc->howto->name);
+ vms_debug (2, "data at %p\n", data);
+ /* _bfd_hexdump (2, data, bfd_get_reloc_size (reloc->howto), 0); */
+#endif
+
+ return bfd_reloc_ok;
+}
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
+static reloc_howto_type alpha_howto_table[] =
+{
+ HOWTO (ALPHA_R_IGNORE, /* Type. */
+ 0, /* Rightshift. */
+ 0, /* Size (0 = byte, 1 = short, 2 = long). */
+ 8, /* Bitsize. */
+ TRUE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "IGNORE", /* Name. */
+ TRUE, /* Partial_inplace. */
+ 0, /* Source mask */
+ 0, /* Dest mask. */
+ TRUE), /* PC rel offset. */
+
+ /* A 64 bit reference to a symbol. */
+ HOWTO (ALPHA_R_REFQUAD, /* Type. */
+ 0, /* Rightshift. */
+ 4, /* Size (0 = byte, 1 = short, 2 = long). */
+ 64, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "REFQUAD", /* Name. */
+ TRUE, /* Partial_inplace. */
+ MINUS_ONE, /* Source mask. */
+ MINUS_ONE, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* A 21 bit branch. The native assembler generates these for
+ branches within the text segment, and also fills in the PC
+ relative offset in the instruction. */
+ HOWTO (ALPHA_R_BRADDR, /* Type. */
+ 2, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 21, /* Bitsize. */
+ TRUE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed, /* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "BRADDR", /* Name. */
+ TRUE, /* Partial_inplace. */
+ 0x1fffff, /* Source mask. */
+ 0x1fffff, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* A hint for a jump to a register. */
+ HOWTO (ALPHA_R_HINT, /* Type. */
+ 2, /* Rightshift. */
+ 1, /* Size (0 = byte, 1 = short, 2 = long). */
+ 14, /* Bitsize. */
+ TRUE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "HINT", /* Name. */
+ TRUE, /* Partial_inplace. */
+ 0x3fff, /* Source mask. */
+ 0x3fff, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* 16 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL16, /* Type. */
+ 0, /* Rightshift. */
+ 1, /* Size (0 = byte, 1 = short, 2 = long). */
+ 16, /* Bitsize. */
+ TRUE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed, /* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "SREL16", /* Name. */
+ TRUE, /* Partial_inplace. */
+ 0xffff, /* Source mask. */
+ 0xffff, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* 32 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL32, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 32, /* Bitsize. */
+ TRUE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed, /* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "SREL32", /* Name. */
+ TRUE, /* Partial_inplace. */
+ 0xffffffff, /* Source mask. */
+ 0xffffffff, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* A 64 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL64, /* Type. */
+ 0, /* Rightshift. */
+ 4, /* Size (0 = byte, 1 = short, 2 = long). */
+ 64, /* Bitsize. */
+ TRUE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed, /* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "SREL64", /* Name. */
+ TRUE, /* Partial_inplace. */
+ MINUS_ONE, /* Source mask. */
+ MINUS_ONE, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* Push a value on the reloc evaluation stack. */
+ HOWTO (ALPHA_R_OP_PUSH, /* Type. */
+ 0, /* Rightshift. */
+ 0, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "OP_PUSH", /* Name. */
+ FALSE, /* Partial_inplace. */
+ 0, /* Source mask. */
+ 0, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* Store the value from the stack at the given address. Store it in
+ a bitfield of size r_size starting at bit position r_offset. */
+ HOWTO (ALPHA_R_OP_STORE, /* Type. */
+ 0, /* Rightshift. */
+ 4, /* Size (0 = byte, 1 = short, 2 = long). */
+ 64, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "OP_STORE", /* Name. */
+ FALSE, /* Partial_inplace. */
+ 0, /* Source mask. */
+ MINUS_ONE, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* Subtract the reloc address from the value on the top of the
+ relocation stack. */
+ HOWTO (ALPHA_R_OP_PSUB, /* Type. */
+ 0, /* Rightshift. */
+ 0, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "OP_PSUB", /* Name. */
+ FALSE, /* Partial_inplace. */
+ 0, /* Source mask. */
+ 0, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* Shift the value on the top of the relocation stack right by the
+ given value. */
+ HOWTO (ALPHA_R_OP_PRSHIFT, /* Type. */
+ 0, /* Rightshift. */
+ 0, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "OP_PRSHIFT", /* Name. */
+ FALSE, /* Partial_inplace. */
+ 0, /* Source mask. */
+ 0, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* Hack. Linkage is done by linker. */
+ HOWTO (ALPHA_R_LINKAGE, /* Type. */
+ 0, /* Rightshift. */
+ 8, /* Size (0 = byte, 1 = short, 2 = long). */
+ 256, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_dont,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "LINKAGE", /* Name. */
+ FALSE, /* Partial_inplace. */
+ 0, /* Source mask. */
+ 0, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* A 32 bit reference to a symbol. */
+ HOWTO (ALPHA_R_REFLONG, /* Type. */
+ 0, /* Rightshift. */
+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
+ 32, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_bitfield, /* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "REFLONG", /* Name. */
+ TRUE, /* Partial_inplace. */
+ 0xffffffff, /* Source mask. */
+ 0xffffffff, /* Dest mask. */
+ FALSE), /* PC rel offset. */
+
+ /* A 64 bit reference to a procedure, written as 32 bit value. */
+ HOWTO (ALPHA_R_CODEADDR, /* Type. */
+ 0, /* Rightshift. */
+ 4, /* Size (0 = byte, 1 = short, 2 = long). */
+ 64, /* Bitsize. */
+ FALSE, /* PC relative. */
+ 0, /* Bitpos. */
+ complain_overflow_signed,/* Complain_on_overflow. */
+ reloc_nil, /* Special_function. */
+ "CODEADDR", /* Name. */
+ FALSE, /* Partial_inplace. */
+ 0xffffffff, /* Source mask. */
+ 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
+ the relocation code on data from the architecture noted. */
+
+static const struct reloc_howto_struct *
+alpha_vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
+{
+ int alpha_type;
+
+ vms_debug2 ((1, "vms_bfd_reloc_type_lookup (%p, %d)\t", abfd, code));
+
+ switch (code)
+ {
+ case BFD_RELOC_16: alpha_type = ALPHA_R_SREL16; break;
+ case BFD_RELOC_32: alpha_type = ALPHA_R_REFLONG; break;
+ case BFD_RELOC_64: alpha_type = ALPHA_R_REFQUAD; break;
+ case BFD_RELOC_CTOR: alpha_type = ALPHA_R_REFQUAD; break;
+ case BFD_RELOC_23_PCREL_S2: alpha_type = ALPHA_R_BRADDR; break;
+ case BFD_RELOC_ALPHA_HINT: alpha_type = ALPHA_R_HINT; break;
+ case BFD_RELOC_16_PCREL: alpha_type = ALPHA_R_SREL16; break;
+ case BFD_RELOC_32_PCREL: alpha_type = ALPHA_R_SREL32; break;
+ 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;
+ }
+ vms_debug2 ((2, "reloc is %s\n", alpha_howto_table[alpha_type].name));
+ return & alpha_howto_table[alpha_type];
+}
+
+static reloc_howto_type *
+alpha_vms_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (alpha_howto_table) / sizeof (alpha_howto_table[0]);
+ i++)
+ if (alpha_howto_table[i].name != NULL
+ && strcasecmp (alpha_howto_table[i].name, r_name) == 0)
+ return &alpha_howto_table[i];
+
+ return NULL;
+}
+\f
+static long
+alpha_vms_get_synthetic_symtab (bfd *abfd,
+ long symcount ATTRIBUTE_UNUSED,
+ asymbol **usyms ATTRIBUTE_UNUSED,
+ long dynsymcount ATTRIBUTE_UNUSED,
+ asymbol **dynsyms ATTRIBUTE_UNUSED,
+ asymbol **ret)
+{
+ asymbol *syms;
+ unsigned int i;
+ unsigned int n = 0;
+
+ syms = (asymbol *) bfd_malloc (PRIV (norm_sym_count) * sizeof (asymbol));
+ *ret = syms;
+ if (syms == NULL)
+ return -1;
+
+ for (i = 0; i < PRIV (gsd_sym_count); i++)
+ {
+ struct vms_symbol_entry *e = PRIV (syms)[i];
+ asymbol *sym;
+ flagword flags;
+ symvalue value;
+ asection *sec;
+ const char *name;
+ char *sname;
+ int l;
+
+ name = e->name;
+ value = 0;
+ flags = BSF_LOCAL | BSF_SYNTHETIC;
+ sec = NULL;
+
+ switch (e->typ)
+ {
+ case EGSD__C_SYM:
+ if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM))
+ {
+ value = e->code_value;
+ sec = PRIV (sections)[e->code_section];
+ }
+ else
+ continue;
+ break;
+
+ case EGSD__C_SYMG:
+ if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM))
+ {
+ bfd_vma sbase = 0;
+ asection *s;
+
+ value = e->code_value;
+
+ /* Find containing section. */
+ for (s = abfd->sections; s; s = s->next)
+ {
+ if (value >= s->vma
+ && s->vma > sbase
+ && !(s->flags & SEC_COFF_SHARED_LIBRARY)
+ && (s->size > 0 || !(e->flags & EGSY__V_REL)))
+ {
+ sbase = s->vma;
+ sec = s;
+ }
+ }
+ value -= sbase;
+ }
+ else
+ continue;
+ break;
+
+ default:
+ abort ();
+ }
+
+ l = strlen (name);
+ sname = bfd_alloc (abfd, l + 5);
+ if (sname == NULL)
+ return FALSE;
+ memcpy (sname, name, l);
+ memcpy (sname + l, "..en", 5);
+
+ sym = &syms[n++];
+ sym->name = sname;
+ sym->section = sec;
+ sym->flags = flags;
+ sym->value = value;
+ sym->udata.p = NULL;
+ }
+
+ return n;
+}
+\f
+/* Private dump. */
+
+static const char *
+vms_time_to_str (unsigned char *buf)
+{
+ time_t t = vms_rawtime_to_time_t (buf);
+ char *res = ctime (&t);
+
+ if (!res)
+ res = "*invalid time*";
+ else
+ res[24] = 0;
+ return res;
+}
+
+static void
+evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
+{
+ struct vms_emh_common *emh = (struct vms_emh_common *)rec;
+ unsigned int subtype;
+
+ subtype = (unsigned)bfd_getl16 (emh->subtyp);
+
+ fprintf (file, _(" EMH %u (len=%u): "), subtype, rec_len);
+
+ switch (subtype)
+ {
+ case EMH__C_MHD:
+ {
+ struct vms_emh_mhd *mhd = (struct vms_emh_mhd *)rec;
+ const char *name;
+
+ fprintf (file, _("Module header\n"));
+ fprintf (file, _(" structure level: %u\n"), mhd->strlvl);
+ fprintf (file, _(" max record size: %u\n"),
+ (unsigned)bfd_getl32 (mhd->recsiz));
+ name = (char *)(mhd + 1);
+ fprintf (file, _(" module name : %.*s\n"), name[0], name + 1);
+ name += name[0] + 1;
+ fprintf (file, _(" module version : %.*s\n"), name[0], name + 1);
+ name += name[0] + 1;
+ fprintf (file, _(" compile date : %.17s\n"), name);
+ }
+ break;
+ case EMH__C_LNM:
+ {
+ fprintf (file, _("Language Processor Name\n"));
+ fprintf (file, _(" language name: %.*s\n"),
+ (int)(rec_len - sizeof (struct vms_emh_common)),
+ (char *)rec + sizeof (struct vms_emh_common));
+ }
+ break;
+ case EMH__C_SRC:
+ {
+ fprintf (file, _("Source Files Header\n"));
+ fprintf (file, _(" file: %.*s\n"),
+ (int)(rec_len - sizeof (struct vms_emh_common)),
+ (char *)rec + sizeof (struct vms_emh_common));
+ }
+ break;
+ case EMH__C_TTL:
+ {
+ fprintf (file, _("Title Text Header\n"));
+ fprintf (file, _(" title: %.*s\n"),
+ (int)(rec_len - sizeof (struct vms_emh_common)),
+ (char *)rec + sizeof (struct vms_emh_common));
+ }
+ break;
+ case EMH__C_CPR:
+ {
+ fprintf (file, _("Copyright Header\n"));
+ fprintf (file, _(" copyright: %.*s\n"),
+ (int)(rec_len - sizeof (struct vms_emh_common)),
+ (char *)rec + sizeof (struct vms_emh_common));
+ }
+ break;
+ default:
+ fprintf (file, _("unhandled emh subtype %u\n"), subtype);
+ break;
+ }
+}
+
+static void
+evax_bfd_print_eeom (FILE *file, unsigned char *rec, unsigned int rec_len)
+{
+ struct vms_eeom *eeom = (struct vms_eeom *)rec;
+
+ fprintf (file, _(" EEOM (len=%u):\n"), rec_len);
+ fprintf (file, _(" number of cond linkage pairs: %u\n"),
+ (unsigned)bfd_getl32 (eeom->total_lps));
+ fprintf (file, _(" completion code: %u\n"),
+ (unsigned)bfd_getl16 (eeom->comcod));
+ if (rec_len > 10)
+ {
+ fprintf (file, _(" transfer addr flags: 0x%02x\n"), eeom->tfrflg);
+ fprintf (file, _(" transfer addr psect: %u\n"),
+ (unsigned)bfd_getl32 (eeom->psindx));
+ fprintf (file, _(" transfer address : 0x%08x\n"),
+ (unsigned)bfd_getl32 (eeom->tfradr));
+ }
+}
+
+static void
+exav_bfd_print_egsy_flags (unsigned int flags, FILE *file)
+{
+ if (flags & EGSY__V_WEAK)
+ fputs (_(" WEAK"), file);
+ if (flags & EGSY__V_DEF)
+ fputs (_(" DEF"), file);
+ if (flags & EGSY__V_UNI)
+ fputs (_(" UNI"), file);
+ if (flags & EGSY__V_REL)
+ fputs (_(" REL"), file);
+ if (flags & EGSY__V_COMM)
+ fputs (_(" COMM"), file);
+ if (flags & EGSY__V_VECEP)
+ fputs (_(" VECEP"), file);
+ if (flags & EGSY__V_NORM)
+ fputs (_(" NORM"), file);
+ if (flags & EGSY__V_QUAD_VAL)
+ fputs (_(" QVAL"), file);
+}
+
+static void
+evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
+{
+ unsigned int off = sizeof (struct vms_egsd);
+ unsigned int n;
+
+ fprintf (file, _(" EGSD (len=%u):\n"), rec_len);
+
+ n = 0;
+ for (off = sizeof (struct vms_egsd); off < rec_len; )
+ {
+ struct vms_egsd_entry *e = (struct vms_egsd_entry *)(rec + off);
+ unsigned int type;
+ unsigned int len;
+
+ type = (unsigned)bfd_getl16 (e->gsdtyp);
+ len = (unsigned)bfd_getl16 (e->gsdsiz);
+
+ fprintf (file, _(" EGSD entry %2u (type: %u, len: %u): "),
+ n, type, len);
+ n++;
+
+ switch (type)
+ {
+ case EGSD__C_PSC:
+ {
+ struct vms_egps *egps = (struct vms_egps *)e;
+ unsigned int flags = bfd_getl16 (egps->flags);
+ unsigned int l;
+
+ fprintf (file, _("PSC - Program section definition\n"));
+ fprintf (file, _(" alignment : 2**%u\n"), egps->align);
+ fprintf (file, _(" flags : 0x%04x"), flags);
+ if (flags & EGPS__V_PIC)
+ fputs (_(" PIC"), file);
+ if (flags & EGPS__V_LIB)
+ fputs (_(" LIB"), file);
+ if (flags & EGPS__V_OVR)
+ fputs (_(" OVR"), file);
+ if (flags & EGPS__V_REL)
+ fputs (_(" REL"), file);
+ if (flags & EGPS__V_GBL)
+ fputs (_(" GBL"), file);
+ if (flags & EGPS__V_SHR)
+ fputs (_(" SHR"), file);
+ if (flags & EGPS__V_EXE)
+ fputs (_(" EXE"), file);
+ if (flags & EGPS__V_RD)
+ fputs (_(" RD"), file);
+ if (flags & EGPS__V_WRT)
+ fputs (_(" WRT"), file);
+ if (flags & EGPS__V_VEC)
+ fputs (_(" VEC"), file);
+ if (flags & EGPS__V_NOMOD)
+ fputs (_(" NOMOD"), file);
+ if (flags & EGPS__V_COM)
+ fputs (_(" COM"), file);
+ if (flags & EGPS__V_ALLOC_64BIT)
+ fputs (_(" 64B"), file);
+ fputc ('\n', file);
+ l = bfd_getl32 (egps->alloc);
+ fprintf (file, _(" alloc (len): %u (0x%08x)\n"), l, l);
+ fprintf (file, _(" name : %.*s\n"),
+ egps->namlng, egps->name);
+ }
+ break;
+ case EGSD__C_SYM:
+ {
+ struct vms_egsy *egsy = (struct vms_egsy *)e;
+ unsigned int flags = bfd_getl16 (egsy->flags);
+
+ if (flags & EGSY__V_DEF)
+ {
+ struct vms_esdf *esdf = (struct vms_esdf *)e;
+
+ fprintf (file, _("SYM - Global symbol definition\n"));
+ fprintf (file, _(" flags: 0x%04x"), flags);
+ exav_bfd_print_egsy_flags (flags, file);
+ fputc ('\n', file);
+ fprintf (file, _(" psect offset: 0x%08x\n"),
+ (unsigned)bfd_getl32 (esdf->value));
+ if (flags & EGSY__V_NORM)
+ {
+ fprintf (file, _(" code address: 0x%08x\n"),
+ (unsigned)bfd_getl32 (esdf->code_address));
+ fprintf (file, _(" psect index for entry point : %u\n"),
+ (unsigned)bfd_getl32 (esdf->ca_psindx));
+ }
+ fprintf (file, _(" psect index : %u\n"),
+ (unsigned)bfd_getl32 (esdf->psindx));
+ fprintf (file, _(" name : %.*s\n"),
+ esdf->namlng, esdf->name);
+ }
+ else
+ {
+ struct vms_esrf *esrf = (struct vms_esrf *)e;
+
+ fprintf (file, _("SYM - Global symbol reference\n"));
+ fprintf (file, _(" name : %.*s\n"),
+ esrf->namlng, esrf->name);
+ }
+ }
+ break;
+ case EGSD__C_SYMG:
+ {
+ struct vms_egst *egst = (struct vms_egst *)e;
+ unsigned int flags = bfd_getl16 (egst->header.flags);
+
+ fprintf (file, _("SYMG - Universal symbol definition\n"));
+ fprintf (file, _(" flags: 0x%04x"), flags);
+ exav_bfd_print_egsy_flags (flags, file);
+ fputc ('\n', file);
+ fprintf (file, _(" symbol vector offset: 0x%08x\n"),
+ (unsigned)bfd_getl32 (egst->value));
+ fprintf (file, _(" entry point: 0x%08x\n"),
+ (unsigned)bfd_getl32 (egst->lp_1));
+ fprintf (file, _(" proc descr : 0x%08x\n"),
+ (unsigned)bfd_getl32 (egst->lp_2));
+ fprintf (file, _(" psect index: %u\n"),
+ (unsigned)bfd_getl32 (egst->psindx));
+ fprintf (file, _(" name : %.*s\n"),
+ egst->namlng, egst->name);
+ }
+ break;
+ case EGSD__C_SYMV:
+ {
+ struct vms_esdfv *esdfv = (struct vms_esdfv *)e;
+ unsigned int flags = bfd_getl16 (esdfv->flags);
+
+ fprintf (file, _("SYMV - Vectored symbol definition\n"));
+ fprintf (file, _(" flags: 0x%04x"), flags);
+ exav_bfd_print_egsy_flags (flags, file);
+ fputc ('\n', file);
+ fprintf (file, _(" vector : 0x%08x\n"),
+ (unsigned)bfd_getl32 (esdfv->vector));
+ fprintf (file, _(" psect offset: %u\n"),
+ (unsigned)bfd_getl32 (esdfv->value));
+ fprintf (file, _(" psect index : %u\n"),
+ (unsigned)bfd_getl32 (esdfv->psindx));
+ fprintf (file, _(" name : %.*s\n"),
+ esdfv->namlng, esdfv->name);
+ }
+ break;
+ case EGSD__C_SYMM:
+ {
+ struct vms_esdfm *esdfm = (struct vms_esdfm *)e;
+ unsigned int flags = bfd_getl16 (esdfm->flags);
+
+ fprintf (file, _("SYMM - Global symbol definition with version\n"));
+ fprintf (file, _(" flags: 0x%04x"), flags);
+ exav_bfd_print_egsy_flags (flags, file);
+ fputc ('\n', file);
+ fprintf (file, _(" version mask: 0x%08x\n"),
+ (unsigned)bfd_getl32 (esdfm->version_mask));
+ fprintf (file, _(" psect offset: %u\n"),
+ (unsigned)bfd_getl32 (esdfm->value));
+ fprintf (file, _(" psect index : %u\n"),
+ (unsigned)bfd_getl32 (esdfm->psindx));
+ fprintf (file, _(" name : %.*s\n"),
+ esdfm->namlng, esdfm->name);
+ }
+ break;
+ default:
+ fprintf (file, _("unhandled egsd entry type %u\n"), type);
+ break;
+ }
+ off += len;
+ }
+}
+
+static void
+evax_bfd_print_hex (FILE *file, const char *pfx,
+ const unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+ unsigned int n;
+
+ n = 0;
+ for (i = 0; i < len; i++)
+ {
+ if (n == 0)
+ fputs (pfx, file);
+ fprintf (file, " %02x", buf[i]);
+ n++;
+ if (n == 16)
+ {
+ n = 0;
+ fputc ('\n', file);
+ }
+ }
+ if (n != 0)
+ fputc ('\n', file);
+}
+
+static void
+evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf, int is_ps)
+{
+ fprintf (file, _(" linkage index: %u, replacement insn: 0x%08x\n"),
+ (unsigned)bfd_getl32 (buf),
+ (unsigned)bfd_getl32 (buf + 16));
+ fprintf (file, _(" psect idx 1: %u, offset 1: 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (buf + 4),
+ (unsigned)bfd_getl32 (buf + 12),
+ (unsigned)bfd_getl32 (buf + 8));
+ fprintf (file, _(" psect idx 2: %u, offset 2: 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (buf + 20),
+ (unsigned)bfd_getl32 (buf + 28),
+ (unsigned)bfd_getl32 (buf + 24));
+ if (is_ps)
+ fprintf (file, _(" psect idx 3: %u, offset 3: 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (buf + 32),
+ (unsigned)bfd_getl32 (buf + 40),
+ (unsigned)bfd_getl32 (buf + 36));
+ else
+ fprintf (file, _(" global name: %.*s\n"), buf[32], buf + 33);
+}
+
+static void
+evax_bfd_print_etir (FILE *file, const char *name,
+ unsigned char *rec, unsigned int rec_len)
+{
+ unsigned int off = sizeof (struct vms_egsd);
+ unsigned int sec_len;
+
+ fprintf (file, _(" %s (len=%u+%u):\n"), name,
+ (unsigned)(rec_len - sizeof (struct vms_eobjrec)),
+ (unsigned)sizeof (struct vms_eobjrec));
+
+ for (off = sizeof (struct vms_eobjrec); off < rec_len; )
+ {
+ struct vms_etir *etir = (struct vms_etir *)(rec + off);
+ unsigned char *buf;
+ unsigned int type;
+ unsigned int size;
+
+ type = bfd_getl16 (etir->rectyp);
+ size = bfd_getl16 (etir->size);
+ buf = rec + off + sizeof (struct vms_etir);
+
+ fprintf (file, _(" (type: %3u, size: 4+%3u): "), type, size - 4);
+ switch (type)
+ {
+ case ETIR__C_STA_GBL:
+ fprintf (file, _("STA_GBL (stack global) %.*s\n"),
+ buf[0], buf + 1);
+ break;
+ case ETIR__C_STA_LW:
+ fprintf (file, _("STA_LW (stack longword) 0x%08x\n"),
+ (unsigned)bfd_getl32 (buf));
+ break;
+ case ETIR__C_STA_QW:
+ fprintf (file, _("STA_QW (stack quadword) 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (buf + 4),
+ (unsigned)bfd_getl32 (buf + 0));
+ break;
+ case ETIR__C_STA_PQ:
+ fprintf (file, _("STA_PQ (stack psect base + offset)\n"));
+ fprintf (file, _(" psect: %u, offset: 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (buf + 0),
+ (unsigned)bfd_getl32 (buf + 8),
+ (unsigned)bfd_getl32 (buf + 4));
+ break;
+ case ETIR__C_STA_LI:
+ fprintf (file, _("STA_LI (stack literal)\n"));
+ break;
+ case ETIR__C_STA_MOD:
+ fprintf (file, _("STA_MOD (stack module)\n"));
+ break;
+ case ETIR__C_STA_CKARG:
+ fprintf (file, _("STA_CKARG (compare procedure argument)\n"));
+ break;
+
+ case ETIR__C_STO_B:
+ fprintf (file, _("STO_B (store byte)\n"));
+ break;
+ case ETIR__C_STO_W:
+ fprintf (file, _("STO_W (store word)\n"));
+ break;
+ case ETIR__C_STO_LW:
+ fprintf (file, _("STO_LW (store longword)\n"));
+ break;
+ case ETIR__C_STO_QW:
+ fprintf (file, _("STO_QW (store quadword)\n"));
+ break;
+ case ETIR__C_STO_IMMR:
+ {
+ unsigned int len = bfd_getl32 (buf);
+ fprintf (file,
+ _("STO_IMMR (store immediate repeat) %u bytes\n"),
+ len);
+ evax_bfd_print_hex (file, " ", buf + 4, len);
+ sec_len += len;
+ }
+ break;
+ case ETIR__C_STO_GBL:
+ fprintf (file, _("STO_GBL (store global) %.*s\n"),
+ buf[0], buf + 1);
+ break;
+ case ETIR__C_STO_CA:
+ fprintf (file, _("STO_CA (store code address) %.*s\n"),
+ buf[0], buf + 1);
+ break;
+ case ETIR__C_STO_RB:
+ fprintf (file, _("STO_RB (store relative branch)\n"));
+ break;
+ case ETIR__C_STO_AB:
+ fprintf (file, _("STO_AB (store absolute branch)\n"));
+ break;
+ case ETIR__C_STO_OFF:
+ fprintf (file, _("STO_OFF (store offset to psect)\n"));
+ break;
+ case ETIR__C_STO_IMM:
+ {
+ unsigned int len = bfd_getl32 (buf);
+ fprintf (file,
+ _("STO_IMM (store immediate) %u bytes\n"),
+ len);
+ evax_bfd_print_hex (file, " ", buf + 4, len);
+ sec_len += len;
+ }
+ break;
+ case ETIR__C_STO_LP_PSB:
+ fprintf (file, _("STO_OFF (store LP with procedure signature)\n"));
+ break;
+ case ETIR__C_STO_HINT_GBL:
+ fprintf (file, _("STO_BR_GBL (store branch global) *todo*\n"));
+ break;
+ case ETIR__C_STO_HINT_PS:
+ fprintf (file, _("STO_BR_PS (store branch psect + offset) *todo*\n"));
+ break;
+
+ case ETIR__C_OPR_NOP:
+ fprintf (file, _("OPR_NOP (no-operation)\n"));
+ break;
+ case ETIR__C_OPR_ADD:
+ fprintf (file, _("OPR_ADD (add)\n"));
+ break;
+ case ETIR__C_OPR_SUB:
+ fprintf (file, _("OPR_SUB (substract)\n"));
+ break;
+ case ETIR__C_OPR_MUL:
+ fprintf (file, _("OPR_MUL (multiply)\n"));
+ break;
+ case ETIR__C_OPR_DIV:
+ fprintf (file, _("OPR_DIV (divide)\n"));
+ break;
+ case ETIR__C_OPR_AND:
+ fprintf (file, _("OPR_AND (logical and)\n"));
+ break;
+ case ETIR__C_OPR_IOR:
+ fprintf (file, _("OPR_IOR (logical inclusive or)\n"));
+ break;
+ case ETIR__C_OPR_EOR:
+ fprintf (file, _("OPR_EOR (logical exclusive or)\n"));
+ break;
+ case ETIR__C_OPR_NEG:
+ fprintf (file, _("OPR_NEG (negate)\n"));
+ break;
+ case ETIR__C_OPR_COM:
+ fprintf (file, _("OPR_COM (complement)\n"));
+ break;
+ case ETIR__C_OPR_INSV:
+ fprintf (file, _("OPR_INSV (insert field)\n"));
+ break;
+ case ETIR__C_OPR_ASH:
+ fprintf (file, _("OPR_ASH (arithmetic shift)\n"));
+ break;
+ case ETIR__C_OPR_USH:
+ fprintf (file, _("OPR_USH (unsigned shift)\n"));
+ break;
+ case ETIR__C_OPR_ROT:
+ fprintf (file, _("OPR_ROT (rotate)\n"));
+ break;
+ case ETIR__C_OPR_SEL:
+ fprintf (file, _("OPR_SEL (select)\n"));
+ break;
+ case ETIR__C_OPR_REDEF:
+ fprintf (file, _("OPR_REDEF (redefine symbol to curr location)\n"));
+ break;
+ case ETIR__C_OPR_DFLIT:
+ fprintf (file, _("OPR_REDEF (define a literal)\n"));
+ break;
+
+ case ETIR__C_STC_LP:
+ fprintf (file, _("STC_LP (store cond linkage pair)\n"));
+ break;
+ case ETIR__C_STC_LP_PSB:
+ fprintf (file,
+ _("STC_LP_PSB (store cond linkage pair + signature)\n"));
+ fprintf (file, _(" linkage index: %u, procedure: %.*s\n"),
+ (unsigned)bfd_getl32 (buf), buf[4], buf + 5);
+ buf += 4 + 1 + buf[4];
+ fprintf (file, _(" signature: %.*s\n"), buf[0], buf + 1);
+ break;
+ case ETIR__C_STC_GBL:
+ fprintf (file, _("STC_GBL (store cond global)\n"));
+ fprintf (file, _(" linkage index: %u, global: %.*s\n"),
+ (unsigned)bfd_getl32 (buf), buf[4], buf + 5);
+ break;
+ case ETIR__C_STC_GCA:
+ fprintf (file, _("STC_GCA (store cond code address)\n"));
+ fprintf (file, _(" linkage index: %u, procedure name: %.*s\n"),
+ (unsigned)bfd_getl32 (buf), buf[4], buf + 5);
+ break;
+ case ETIR__C_STC_PS:
+ fprintf (file, _("STC_PS (store cond psect + offset)\n"));
+ fprintf (file,
+ _(" linkage index: %u, psect: %u, offset: 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (buf),
+ (unsigned)bfd_getl32 (buf + 4),
+ (unsigned)bfd_getl32 (buf + 12),
+ (unsigned)bfd_getl32 (buf + 8));
+ break;
+ case ETIR__C_STC_NOP_GBL:
+ fprintf (file, _("STC_NOP_GBL (store cond NOP at global addr)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 0);
+ break;
+ case ETIR__C_STC_NOP_PS:
+ fprintf (file, _("STC_NOP_PS (store cond NOP at psect + offset)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 1);
+ break;
+ case ETIR__C_STC_BSR_GBL:
+ fprintf (file, _("STC_BSR_GBL (store cond BSR at global addr)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 0);
+ break;
+ case ETIR__C_STC_BSR_PS:
+ fprintf (file, _("STC_BSR_PS (store cond BSR at psect + offset)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 1);
+ break;
+ case ETIR__C_STC_LDA_GBL:
+ fprintf (file, _("STC_LDA_GBL (store cond LDA at global addr)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 0);
+ break;
+ case ETIR__C_STC_LDA_PS:
+ fprintf (file, _("STC_LDA_PS (store cond LDA at psect + offset)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 1);
+ break;
+ case ETIR__C_STC_BOH_GBL:
+ fprintf (file, _("STC_BOH_GBL (store cond BOH at global addr)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 0);
+ break;
+ case ETIR__C_STC_BOH_PS:
+ fprintf (file, _("STC_BOH_PS (store cond BOH at psect + offset)\n"));
+ evax_bfd_print_etir_stc_ir (file, buf, 1);
+ break;
+ case ETIR__C_STC_NBH_GBL:
+ fprintf (file,
+ _("STC_NBH_GBL (store cond or hint at global addr)\n"));
+ break;
+ case ETIR__C_STC_NBH_PS:
+ fprintf (file,
+ _("STC_NBH_PS (store cond or hint at psect + offset)\n"));
+ break;
+
+ case ETIR__C_CTL_SETRB:
+ fprintf (file, _("CTL_SETRB (set relocation base)\n"));
+ sec_len += 4;
+ break;
+ case ETIR__C_CTL_AUGRB:
+ {
+ unsigned int val = bfd_getl32 (buf);
+ fprintf (file, _("CTL_AUGRB (augment relocation base) %u\n"), val);
+ }
+ break;
+ case ETIR__C_CTL_DFLOC:
+ fprintf (file, _("CTL_DFLOC (define location)\n"));
+ break;
+ case ETIR__C_CTL_STLOC:
+ fprintf (file, _("CTL_STLOC (set location)\n"));
+ break;
+ case ETIR__C_CTL_STKDL:
+ fprintf (file, _("CTL_STKDL (stack defined location)\n"));
+ break;
+ default:
+ fprintf (file, _("*unhandled*\n"));
+ break;
+ }
+ off += size;
+ }
+}
+
+static void
+evax_bfd_print_eobj (struct bfd *abfd, FILE *file)
+{
+ bfd_boolean is_first = TRUE;
+ bfd_boolean has_records = FALSE;
+
+ while (1)
+ {
+ unsigned int rec_len;
+ unsigned int pad_len;
+ unsigned char *rec;
+ unsigned int hdr_size;
+ unsigned int type;
+
+ if (is_first)
+ {
+ unsigned char buf[6];
+
+ is_first = FALSE;
+
+ /* Read 6 bytes. */
+ if (bfd_bread (buf, sizeof (buf), abfd) != sizeof (buf))
+ {
+ fprintf (file, _("cannot read GST record length\n"));
+ return;
+ }
+ rec_len = bfd_getl16 (buf + 0);
+ if (rec_len == bfd_getl16 (buf + 4)
+ && bfd_getl16 (buf + 2) == EOBJ__C_EMH)
+ {
+ /* The format is raw: record-size, type, record-size. */
+ has_records = TRUE;
+ pad_len = (rec_len + 1) & ~1U;
+ hdr_size = 4;
+ }
+ else if (rec_len == EOBJ__C_EMH)
+ {
+ has_records = FALSE;
+ pad_len = bfd_getl16 (buf + 2);
+ hdr_size = 6;
+ }
+ else
+ {
+ /* Ill-formed. */
+ fprintf (file, _("cannot find EMH in first GST record\n"));
+ return;
+ }
+ rec = bfd_malloc (pad_len);
+ memcpy (rec, buf + sizeof (buf) - hdr_size, hdr_size);
+ }
+ else
+ {
+ unsigned int rec_len2 = 0;
+ unsigned char hdr[4];
+
+ if (has_records)
+ {
+ unsigned char buf_len[2];
+
+ if (bfd_bread (buf_len, sizeof (buf_len), abfd)
+ != sizeof (buf_len))
+ {
+ fprintf (file, _("cannot read GST record length\n"));
+ return;
+ }
+ rec_len2 = (unsigned)bfd_getl16 (buf_len);
+ }
+
+ if (bfd_bread (hdr, sizeof (hdr), abfd) != sizeof (hdr))
+ {
+ fprintf (file, _("cannot read GST record header\n"));
+ return;
+ }
+ rec_len = (unsigned)bfd_getl16 (hdr + 2);
+ if (has_records)
+ pad_len = (rec_len + 1) & ~1U;
+ else
+ pad_len = rec_len;
+ rec = bfd_malloc (pad_len);
+ memcpy (rec, hdr, sizeof (hdr));
+ hdr_size = sizeof (hdr);
+ if (has_records && rec_len2 != rec_len)
+ {
+ fprintf (file, _(" corrupted GST\n"));
+ break;
+ }
+ }
+
+ if (bfd_bread (rec + hdr_size, pad_len - hdr_size, abfd)
+ != pad_len - hdr_size)
+ {
+ fprintf (file, _("cannot read GST record\n"));
+ return;
+ }
+
+ type = (unsigned)bfd_getl16 (rec);
+
+ switch (type)
+ {
+ case EOBJ__C_EMH:
+ evax_bfd_print_emh (file, rec, rec_len);
+ break;
+ case EOBJ__C_EGSD:
+ evax_bfd_print_egsd (file, rec, rec_len);
+ break;
+ case EOBJ__C_EEOM:
+ evax_bfd_print_eeom (file, rec, rec_len);
+ free (rec);
+ return;
+ break;
+ case EOBJ__C_ETIR:
+ evax_bfd_print_etir (file, "ETIR", rec, rec_len);
+ break;
+ case EOBJ__C_EDBG:
+ evax_bfd_print_etir (file, "EDBG", rec, rec_len);
+ break;
+ case EOBJ__C_ETBT:
+ evax_bfd_print_etir (file, "ETBT", rec, rec_len);
+ break;
+ default:
+ fprintf (file, _(" unhandled EOBJ record type %u\n"), type);
+ break;
+ }
+ free (rec);
+ }
+}
+
+static void
+evax_bfd_print_relocation_records (FILE *file, const unsigned char *rel,
+ unsigned int stride)
+{
+ while (1)
+ {
+ unsigned int base;
+ unsigned int count;
+ unsigned int j;
+
+ count = bfd_getl32 (rel + 0);
+
+ if (count == 0)
+ break;
+ base = bfd_getl32 (rel + 4);
+
+ fprintf (file, _(" bitcount: %u, base addr: 0x%08x\n"),
+ count, base);
+
+ rel += 8;
+ for (j = 0; count > 0; j += 4, count -= 32)
+ {
+ unsigned int k;
+ unsigned int n = 0;
+ unsigned int val;
+
+ val = bfd_getl32 (rel);
+ rel += 4;
+
+ fprintf (file, _(" bitmap: 0x%08x (count: %u):\n"), val, count);
+
+ for (k = 0; k < 32; k++)
+ if (val & (1 << k))
+ {
+ if (n == 0)
+ fputs (" ", file);
+ fprintf (file, _(" %08x"), base + (j * 8 + k) * stride);
+ n++;
+ if (n == 8)
+ {
+ fputs ("\n", file);
+ n = 0;
+ }
+ }
+ if (n)
+ fputs ("\n", file);
+ }
+ }
+}
+
+static void
+evax_bfd_print_address_fixups (FILE *file, const unsigned char *rel)
+{
+ while (1)
+ {
+ unsigned int j;
+ unsigned int count;
+
+ count = bfd_getl32 (rel + 0);
+ if (count == 0)
+ return;
+ fprintf (file, _(" image %u (%u entries)\n"),
+ (unsigned)bfd_getl32 (rel + 4), count);
+ rel += 8;
+ for (j = 0; j < count; j++)
+ {
+ fprintf (file, _(" offset: 0x%08x, val: 0x%08x\n"),
+ (unsigned)bfd_getl32 (rel + 0),
+ (unsigned)bfd_getl32 (rel + 4));
+ rel += 8;
+ }
+ }
+}
+
+static void
+evax_bfd_print_reference_fixups (FILE *file, const unsigned char *rel)
+{
+ unsigned int count;
+
+ while (1)
+ {
+ unsigned int j;
+ unsigned int n = 0;
+
+ count = bfd_getl32 (rel + 0);
+ if (count == 0)
+ break;
+ fprintf (file, _(" image %u (%u entries), offsets:\n"),
+ (unsigned)bfd_getl32 (rel + 4), count);
+ rel += 8;
+ for (j = 0; j < count; j++)
+ {
+ if (n == 0)
+ fputs (" ", file);
+ fprintf (file, _(" 0x%08x"), (unsigned)bfd_getl32 (rel));
+ n++;
+ if (n == 7)
+ {
+ fputs ("\n", file);
+ n = 0;
+ }
+ rel += 4;
+ }
+ if (n)
+ fputs ("\n", file);
+ }
+}
+
+static void
+evax_bfd_print_indent (int indent, FILE *file)
+{
+ for (; indent; indent--)
+ fputc (' ', file);
+}
+
+static const char *
+evax_bfd_get_dsc_name (unsigned int v)
+{
+ switch (v)
+ {
+ case DSC__K_DTYPE_Z:
+ return "Z (Unspecified)";
+ case DSC__K_DTYPE_V:
+ return "V (Bit)";
+ case DSC__K_DTYPE_BU:
+ return "BU (Byte logical)";
+ case DSC__K_DTYPE_WU:
+ return "WU (Word logical)";
+ case DSC__K_DTYPE_LU:
+ return "LU (Longword logical)";
+ case DSC__K_DTYPE_QU:
+ return "QU (Quadword logical)";
+ case DSC__K_DTYPE_B:
+ return "B (Byte integer)";
+ case DSC__K_DTYPE_W:
+ return "W (Word integer)";
+ case DSC__K_DTYPE_L:
+ return "L (Longword integer)";
+ case DSC__K_DTYPE_Q:
+ return "Q (Quadword integer)";
+ case DSC__K_DTYPE_F:
+ return "F (Single-precision floating)";
+ case DSC__K_DTYPE_D:
+ return "D (Double-precision floating)";
+ case DSC__K_DTYPE_FC:
+ return "FC (Complex)";
+ case DSC__K_DTYPE_DC:
+ return "DC (Double-precision Complex)";
+ case DSC__K_DTYPE_T:
+ return "T (ASCII text string)";
+ case DSC__K_DTYPE_NU:
+ return "NU (Numeric string, unsigned)";
+ case DSC__K_DTYPE_NL:
+ return "NL (Numeric string, left separate sign)";
+ case DSC__K_DTYPE_NLO:
+ return "NLO (Numeric string, left overpunched sign)";
+ case DSC__K_DTYPE_NR:
+ return "NR (Numeric string, right separate sign)";
+ case DSC__K_DTYPE_NRO:
+ return "NRO (Numeric string, right overpunched sig)";
+ case DSC__K_DTYPE_NZ:
+ return "NZ (Numeric string, zoned sign)";
+ case DSC__K_DTYPE_P:
+ return "P (Packed decimal string)";
+ case DSC__K_DTYPE_ZI:
+ return "ZI (Sequence of instructions)";
+ case DSC__K_DTYPE_ZEM:
+ return "ZEM (Procedure entry mask)";
+ case DSC__K_DTYPE_DSC:
+ return "DSC (Descriptor, used for arrays of dyn strings)";
+ case DSC__K_DTYPE_OU:
+ return "OU (Octaword logical)";
+ case DSC__K_DTYPE_O:
+ return "O (Octaword integer)";
+ case DSC__K_DTYPE_G:
+ return "G (Double precision G floating, 64 bit)";
+ case DSC__K_DTYPE_H:
+ return "H (Quadruple precision floating, 128 bit)";
+ case DSC__K_DTYPE_GC:
+ return "GC (Double precision complex, G floating)";
+ case DSC__K_DTYPE_HC:
+ return "HC (Quadruple precision complex, H floating)";
+ case DSC__K_DTYPE_CIT:
+ return "CIT (COBOL intermediate temporary)";
+ case DSC__K_DTYPE_BPV:
+ return "BPV (Bound Procedure Value)";
+ case DSC__K_DTYPE_BLV:
+ return "BLV (Bound Label Value)";
+ case DSC__K_DTYPE_VU:
+ return "VU (Bit Unaligned)";
+ case DSC__K_DTYPE_ADT:
+ return "ADT (Absolute Date-Time)";
+ case DSC__K_DTYPE_VT:
+ return "VT (Varying Text)";
+ case DSC__K_DTYPE_T2:
+ return "T2 (16-bit char)";
+ case DSC__K_DTYPE_VT2:
+ return "VT2 (16-bit varying char)";
+ default:
+ return "?? (unknown)";
+ }
+}
+
+static void
+evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file)
+{
+ unsigned char bclass = buf[3];
+ unsigned char dtype = buf[2];
+ unsigned int len = (unsigned)bfd_getl16 (buf);
+ unsigned int pointer = (unsigned)bfd_getl32 (buf + 4);
+
+ evax_bfd_print_indent (indent, file);
+
+ if (len == 1 && pointer == 0xffffffffUL)
+ {
+ /* 64 bits. */
+ fprintf (file, _("64 bits *unhandled*\n"));
+ }
+ else
+ {
+ fprintf (file, _("class: %u, dtype: %u, length: %u, pointer: 0x%08x\n"),
+ bclass, dtype, len, pointer);
+ switch (bclass)
+ {
+ case DSC__K_CLASS_NCA:
+ {
+ const struct vms_dsc_nca *dsc = (const void *)buf;
+ unsigned int i;
+ const unsigned char *b;
+
+ evax_bfd_print_indent (indent, file);
+ fprintf (file, _("non-contiguous array of %s\n"),
+ evax_bfd_get_dsc_name (dsc->dtype));
+ evax_bfd_print_indent (indent + 1, file);
+ fprintf (file,
+ _("dimct: %u, aflags: 0x%02x, digits: %u, scale: %u\n"),
+ dsc->dimct, dsc->aflags, dsc->digits, dsc->scale);
+ evax_bfd_print_indent (indent + 1, file);
+ fprintf (file,
+ _("arsize: %u, a0: 0x%08x\n"),
+ (unsigned)bfd_getl32 (dsc->arsize),
+ (unsigned)bfd_getl32 (dsc->a0));
+ evax_bfd_print_indent (indent + 1, file);
+ fprintf (file, _("Strides:\n"));
+ b = buf + sizeof (*dsc);
+ for (i = 0; i < dsc->dimct; i++)
+ {
+ evax_bfd_print_indent (indent + 2, file);
+ fprintf (file, _("[%u]: %u\n"), i + 1,
+ (unsigned)bfd_getl32 (b));
+ b += 4;
+ }
+ evax_bfd_print_indent (indent + 1, file);
+ fprintf (file, _("Bounds:\n"));
+ b = buf + sizeof (*dsc);
+ for (i = 0; i < dsc->dimct; i++)
+ {
+ evax_bfd_print_indent (indent + 2, file);
+ fprintf (file, _("[%u]: Lower: %u, upper: %u\n"), i + 1,
+ (unsigned)bfd_getl32 (b + 0),
+ (unsigned)bfd_getl32 (b + 4));
+ b += 8;
+ }
+ }
+ break;
+ case DSC__K_CLASS_UBS:
+ {
+ const struct vms_dsc_ubs *ubs = (const void *)buf;
+
+ evax_bfd_print_indent (indent, file);
+ fprintf (file, _("unaligned bit-string of %s\n"),
+ evax_bfd_get_dsc_name (ubs->dtype));
+ evax_bfd_print_indent (indent + 1, file);
+ fprintf (file,
+ _("base: %u, pos: %u\n"),
+ (unsigned)bfd_getl32 (ubs->base),
+ (unsigned)bfd_getl32 (ubs->pos));
+ }
+ break;
+ default:
+ fprintf (file, _("*unhandled*\n"));
+ break;
+ }
+ }
+}
+
+static unsigned int
+evax_bfd_print_valspec (const unsigned char *buf, int indent, FILE *file)
+{
+ unsigned int vflags = buf[0];
+ unsigned int value = (unsigned)bfd_getl32 (buf + 1);
+ unsigned int len = 5;
+
+ evax_bfd_print_indent (indent, file);
+ fprintf (file, _("vflags: 0x%02x, value: 0x%08x "), vflags, value);
+ buf += 5;
+
+ switch (vflags)
+ {
+ case DST__K_VFLAGS_NOVAL:
+ fprintf (file, _("(no value)\n"));
+ break;
+ case DST__K_VFLAGS_NOTACTIVE:
+ fprintf (file, _("(not active)\n"));
+ break;
+ case DST__K_VFLAGS_UNALLOC:
+ fprintf (file, _("(not allocated)\n"));
+ break;
+ case DST__K_VFLAGS_DSC:
+ fprintf (file, _("(descriptor)\n"));
+ evax_bfd_print_desc (buf + value, indent + 1, file);
+ break;
+ case DST__K_VFLAGS_TVS:
+ fprintf (file, _("(trailing value)\n"));
+ break;
+ case DST__K_VS_FOLLOWS:
+ fprintf (file, _("(value spec follows)\n"));
+ break;
+ case DST__K_VFLAGS_BITOFFS:
+ fprintf (file, _("(at bit offset %u)\n"), value);
+ break;
+ default:
+ fprintf (file, _("(reg: %u, disp: %u, indir: %u, kind: "),
+ (vflags & DST__K_REGNUM_MASK) >> DST__K_REGNUM_SHIFT,
+ vflags & DST__K_DISP ? 1 : 0,
+ vflags & DST__K_INDIR ? 1 : 0);
+ switch (vflags & DST__K_VALKIND_MASK)
+ {
+ case DST__K_VALKIND_LITERAL:
+ fputs (_("literal"), file);
+ break;
+ case DST__K_VALKIND_ADDR:
+ fputs (_("address"), file);
+ break;
+ case DST__K_VALKIND_DESC:
+ fputs (_("desc"), file);
+ break;
+ case DST__K_VALKIND_REG:
+ fputs (_("reg"), file);
+ break;
+ }
+ fputs (")\n", file);
+ break;
+ }
+ return len;
+}
+
+static void
+evax_bfd_print_typspec (const unsigned char *buf, int indent, FILE *file)
+{
+ unsigned char kind = buf[2];
+ unsigned int len = (unsigned)bfd_getl16 (buf);
+
+ evax_bfd_print_indent (indent, file);
+ fprintf (file, ("len: %2u, kind: %2u "), len, kind);
+ buf += 3;
+ switch (kind)
+ {
+ case DST__K_TS_ATOM:
+ fprintf (file, ("atomic, type=0x%02x %s\n"),
+ buf[0], evax_bfd_get_dsc_name (buf[0]));
+ break;
+ case DST__K_TS_IND:
+ fprintf (file, ("indirect, defined at 0x%08x\n"),
+ (unsigned)bfd_getl32 (buf));
+ break;
+ case DST__K_TS_TPTR:
+ fprintf (file, ("typed pointer\n"));
+ evax_bfd_print_typspec (buf, indent + 1, file);
+ break;
+ case DST__K_TS_PTR:
+ fprintf (file, ("pointer\n"));
+ break;
+ case DST__K_TS_ARRAY:
+ {
+ const unsigned char *vs;
+ unsigned int vec_len;
+ unsigned int i;
+
+ fprintf (file, ("array, dim: %u, bitmap: "), buf[0]);
+ vec_len = (buf[0] + 1 + 7) / 8;
+ for (i = 0; i < vec_len; i++)
+ fprintf (file, " %02x", buf[i + 1]);
+ fputc ('\n', file);
+ vs = buf + 1 + vec_len;
+ evax_bfd_print_indent (indent, file);
+ fprintf (file, ("array descriptor:\n"));
+ vs += evax_bfd_print_valspec (vs, indent + 1, file);
+ for (i = 0; i < buf[0] + 1U; i++)
+ if (buf[1 + i / 8] & (1 << (i % 8)))
+ {
+ evax_bfd_print_indent (indent, file);
+ if (i == 0)
+ fprintf (file, ("type spec for element:\n"));
+ else
+ fprintf (file, ("type spec for subscript %u:\n"), i);
+ evax_bfd_print_typspec (vs, indent + 1, file);
+ vs += bfd_getl16 (vs);
+ }
+ }
+ break;
+ default:
+ fprintf (file, ("*unhandled*\n"));
+ }
+}
+
+static void
+evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
+{
+ unsigned int off = 0;
+ unsigned int pc = 0;
+ unsigned int line = 0;
+
+ fprintf (file, _("Debug symbol table:\n"));
+
+ while (dst_size > 0)
+ {
+ struct vms_dst_header dsth;
+ unsigned int len;
+ unsigned int type;
+ unsigned char *buf;
+
+ if (bfd_bread (&dsth, sizeof (dsth), abfd) != sizeof (dsth))
+ {
+ fprintf (file, _("cannot read DST header\n"));
+ return;
+ }
+ len = bfd_getl16 (dsth.length);
+ type = bfd_getl16 (dsth.type);
+ fprintf (file, _(" type: %3u, len: %3u (at 0x%08x): "),
+ type, len, off);
+ if (len == 0)
+ {
+ fputc ('\n', file);
+ break;
+ }
+ len++;
+ dst_size -= len;
+ off += len;
+ len -= sizeof (dsth);
+ buf = bfd_malloc (len);
+ if (bfd_bread (buf, len, abfd) != len)
+ {
+ fprintf (file, _("cannot read DST symbol\n"));
+ return;
+ }
+ switch (type)
+ {
+ case DSC__K_DTYPE_V:
+ case DSC__K_DTYPE_BU:
+ case DSC__K_DTYPE_WU:
+ case DSC__K_DTYPE_LU:
+ case DSC__K_DTYPE_QU:
+ case DSC__K_DTYPE_B:
+ case DSC__K_DTYPE_W:
+ case DSC__K_DTYPE_L:
+ case DSC__K_DTYPE_Q:
+ case DSC__K_DTYPE_F:
+ case DSC__K_DTYPE_D:
+ case DSC__K_DTYPE_FC:
+ case DSC__K_DTYPE_DC:
+ case DSC__K_DTYPE_T:
+ case DSC__K_DTYPE_NU:
+ case DSC__K_DTYPE_NL:
+ case DSC__K_DTYPE_NLO:
+ case DSC__K_DTYPE_NR:
+ case DSC__K_DTYPE_NRO:
+ case DSC__K_DTYPE_NZ:
+ case DSC__K_DTYPE_P:
+ case DSC__K_DTYPE_ZI:
+ case DSC__K_DTYPE_ZEM:
+ case DSC__K_DTYPE_DSC:
+ case DSC__K_DTYPE_OU:
+ case DSC__K_DTYPE_O:
+ case DSC__K_DTYPE_G:
+ case DSC__K_DTYPE_H:
+ case DSC__K_DTYPE_GC:
+ case DSC__K_DTYPE_HC:
+ case DSC__K_DTYPE_CIT:
+ case DSC__K_DTYPE_BPV:
+ case DSC__K_DTYPE_BLV:
+ case DSC__K_DTYPE_VU:
+ case DSC__K_DTYPE_ADT:
+ case DSC__K_DTYPE_VT:
+ case DSC__K_DTYPE_T2:
+ case DSC__K_DTYPE_VT2:
+ fprintf (file, _("standard data: %s\n"),
+ evax_bfd_get_dsc_name (type));
+ evax_bfd_print_valspec (buf, 4, file);
+ fprintf (file, _(" name: %.*s\n"), buf[5], buf + 6);
+ break;
+ case DST__K_MODBEG:
+ {
+ struct vms_dst_modbeg *dst = (void *)buf;
+ const char *name = (const char *)buf + sizeof (*dst);
+
+ fprintf (file, _("modbeg\n"));
+ fprintf (file, _(" flags: %d, language: %u, "
+ "major: %u, minor: %u\n"),
+ dst->flags,
+ (unsigned)bfd_getl32 (dst->language),
+ (unsigned)bfd_getl16 (dst->major),
+ (unsigned)bfd_getl16 (dst->minor));
+ fprintf (file, _(" module name: %.*s\n"),
+ name[0], name + 1);
+ name += name[0] + 1;
+ fprintf (file, _(" compiler : %.*s\n"),
+ name[0], name + 1);
+ }
+ break;
+ case DST__K_MODEND:
+ fprintf (file, _("modend\n"));
+ break;
+ case DST__K_RTNBEG:
+ {
+ struct vms_dst_rtnbeg *dst = (void *)buf;
+ const char *name = (const char *)buf + sizeof (*dst);
+
+ fputs (_("rtnbeg\n"), file);
+ fprintf (file, _(" flags: %u, address: 0x%08x, "
+ "pd-address: 0x%08x\n"),
+ dst->flags,
+ (unsigned)bfd_getl32 (dst->address),
+ (unsigned)bfd_getl32 (dst->pd_address));
+ fprintf (file, _(" routine name: %.*s\n"),
+ name[0], name + 1);
+ }
+ break;
+ case DST__K_RTNEND:
+ {
+ struct vms_dst_rtnend *dst = (void *)buf;
+
+ fprintf (file, _("rtnend: size 0x%08x\n"),
+ (unsigned)bfd_getl32 (dst->size));
+ }
+ break;
+ case DST__K_PROLOG:
+ {
+ struct vms_dst_prolog *dst = (void *)buf;
+
+ fprintf (file, _("prolog: bkpt address 0x%08x\n"),
+ (unsigned)bfd_getl32 (dst->bkpt_addr));
+ }
+ break;
+ case DST__K_EPILOG:
+ {
+ struct vms_dst_epilog *dst = (void *)buf;
+
+ fprintf (file, _("epilog: flags: %u, count: %u\n"),
+ dst->flags, (unsigned)bfd_getl32 (dst->count));
+ }
+ break;
+ case DST__K_BLKBEG:
+ {
+ struct vms_dst_blkbeg *dst = (void *)buf;
+ const char *name = (const char *)buf + sizeof (*dst);
+
+ fprintf (file, _("blkbeg: address: 0x%08x, name: %.*s\n"),
+ (unsigned)bfd_getl32 (dst->address),
+ name[0], name + 1);
+ }
+ break;
+ case DST__K_BLKEND:
+ {
+ struct vms_dst_blkend *dst = (void *)buf;
+
+ fprintf (file, _("blkend: size: 0x%08x\n"),
+ (unsigned)bfd_getl32 (dst->size));
+ }
+ break;
+ case DST__K_TYPSPEC:
+ {
+ fprintf (file, _("typspec (len: %u)\n"), len);
+ fprintf (file, _(" name: %.*s\n"), buf[0], buf + 1);
+ evax_bfd_print_typspec (buf + 1 + buf[0], 5, file);
+ }
+ break;
+ case DST__K_SEPTYP:
+ {
+ fprintf (file, _("septyp, name: %.*s\n"), buf[5], buf + 6);
+ evax_bfd_print_valspec (buf, 4, file);
+ }
+ break;
+ case DST__K_RECBEG:
+ {
+ struct vms_dst_recbeg *recbeg = (void *)buf;
+ const char *name = (const char *)buf + sizeof (*recbeg);
+
+ fprintf (file, _("recbeg: name: %.*s\n"), name[0], name + 1);
+ evax_bfd_print_valspec (buf, 4, file);
+ fprintf (file, (" len: %u bits\n"),
+ (unsigned)bfd_getl32 (name + 1 + name[0]));
+ }
+ break;
+ case DST__K_RECEND:
+ fprintf (file, _("recend\n"));
+ break;
+ case DST__K_ENUMBEG:
+ fprintf (file, _("enumbeg, len: %u, name: %.*s\n"),
+ buf[0], buf[1], buf + 2);
+ break;
+ case DST__K_ENUMELT:
+ fprintf (file, _("enumelt, name: %.*s\n"), buf[5], buf + 6);
+ evax_bfd_print_valspec (buf, 4, file);
+ break;
+ case DST__K_ENUMEND:
+ fprintf (file, _("enumend\n"));
+ break;
+ case DST__K_LABEL:
+ {
+ struct vms_dst_label *lab = (void *)buf;
+ fprintf (file, ("label, name: %.*s\n"),
+ lab->name[0], lab->name + 1);
+ fprintf (file, (" address: 0x%08x\n"),
+ (unsigned)bfd_getl32 (lab->value));
+ }
+ break;
+ case DST__K_DIS_RANGE:
+ {
+ unsigned int cnt = bfd_getl32 (buf);
+ unsigned char *rng = buf + 4;
+ unsigned int i;
+
+ fprintf (file, _("discontiguous range (nbr: %u)\n"), cnt);
+ for (i = 0; i < cnt; i++, rng += 8)
+ fprintf (file, _(" address: 0x%08x, size: %u\n"),
+ (unsigned)bfd_getl32 (rng),
+ (unsigned)bfd_getl32 (rng + 4));
+
+ }
+ break;
+ case DST__K_LINE_NUM:
+ {
+ unsigned char *buf_orig = buf;
+
+ fprintf (file, _("line num (len: %u)\n"), len);
+
+ while (len > 0)
+ {
+ signed char cmd;
+ unsigned char cmdlen;
+ unsigned int val;
+
+ cmd = buf[0];
+ cmdlen = 0;
+
+ fputs (" ", file);
+
+ switch (cmd)
+ {
+ case DST__K_DELTA_PC_W:
+ val = bfd_getl16 (buf + 1);
+ fprintf (file, _("delta_pc_w %u\n"), val);
+ pc += val;
+ line++;
+ cmdlen = 3;
+ break;
+ case DST__K_INCR_LINUM:
+ val = buf[1];
+ fprintf (file, _("incr_linum: +%u\n"), val);
+ line += val;
+ cmdlen = 2;
+ break;
+ case DST__K_INCR_LINUM_W:
+ val = bfd_getl16 (buf + 1);
+ fprintf (file, _("incr_linum: +%u\n"), val);
+ line += val;
+ cmdlen = 3;
+ break;
+ case DST__K_SET_LINUM:
+ line = (unsigned)bfd_getl16 (buf + 1);
+ fprintf (file, _("set_line_num %u\n"), line);
+ cmdlen = 3;
+ break;
+ case DST__K_SET_LINUM_B:
+ line = buf[1];
+ fprintf (file, _("set_line_num_b %u\n"), line);
+ cmdlen = 2;
+ break;
+ case DST__K_SET_LINUM_L:
+ line = (unsigned)bfd_getl32 (buf + 1);
+ fprintf (file, _("set_line_num_l %u\n"), line);
+ cmdlen = 5;
+ break;
+ case DST__K_SET_ABS_PC:
+ pc = (unsigned)bfd_getl32 (buf + 1);
+ fprintf (file, _("set_abs_pc: 0x%08x\n"), pc);
+ cmdlen = 5;
+ break;
+ case DST__K_DELTA_PC_L:
+ fprintf (file, _("delta_pc_l: +0x%08x\n"),
+ (unsigned)bfd_getl32 (buf + 1));
+ cmdlen = 5;
+ break;
+ case DST__K_TERM:
+ fprintf (file, _("term: 0x%02x"), buf[1]);
+ pc += buf[1];
+ fprintf (file, _(" pc: 0x%08x\n"), pc);
+ cmdlen = 2;
+ break;
+ case DST__K_TERM_W:
+ val = bfd_getl16 (buf + 1);
+ fprintf (file, _("term_w: 0x%04x"), val);
+ pc += val;
+ fprintf (file, _(" pc: 0x%08x\n"), pc);
+ cmdlen = 3;
+ break;
+ default:
+ if (cmd <= 0)
+ {
+ fprintf (file, _("delta pc +%-4d"), -cmd);
+ line++; /* FIXME: curr increment. */
+ pc += -cmd;
+ fprintf (file, _(" pc: 0x%08x line: %5u\n"),
+ pc, line);
+ cmdlen = 1;
+ }
+ else
+ fprintf (file, _(" *unhandled* cmd %u\n"), cmd);
+ break;
+ }
+ if (cmdlen == 0)
+ break;
+ len -= cmdlen;
+ buf += cmdlen;
+ }
+ buf = buf_orig;
+ }
+ break;
+ case DST__K_SOURCE:
+ {
+ unsigned char *buf_orig = buf;
+
+ fprintf (file, _("source (len: %u)\n"), len);
+
+ while (len > 0)
+ {
+ signed char cmd = buf[0];
+ unsigned char cmdlen = 0;
+
+ switch (cmd)
+ {
+ case DST__K_SRC_DECLFILE:
+ {
+ struct vms_dst_src_decl_src *src = (void *)(buf + 1);
+ const char *name;
+
+ fprintf (file, _(" declfile: len: %u, flags: %u, "
+ "fileid: %u\n"),
+ src->length, src->flags,
+ (unsigned)bfd_getl16 (src->fileid));
+ fprintf (file, _(" rms: cdt: 0x%08x %08x, "
+ "ebk: 0x%08x, ffb: 0x%04x, "
+ "rfo: %u\n"),
+ (unsigned)bfd_getl32 (src->rms_cdt + 4),
+ (unsigned)bfd_getl32 (src->rms_cdt + 0),
+ (unsigned)bfd_getl32 (src->rms_ebk),
+ (unsigned)bfd_getl16 (src->rms_ffb),
+ src->rms_rfo);
+ name = (const char *)buf + 1 + sizeof (*src);
+ fprintf (file, _(" filename : %.*s\n"),
+ name[0], name + 1);
+ name += name[0] + 1;
+ fprintf (file, _(" module name: %.*s\n"),
+ name[0], name + 1);
+ cmdlen = 2 + src->length;
+ }
+ break;
+ case DST__K_SRC_SETFILE:
+ fprintf (file, _(" setfile %u\n"),
+ (unsigned)bfd_getl16 (buf + 1));
+ cmdlen = 3;
+ break;
+ case DST__K_SRC_SETREC_W:
+ fprintf (file, _(" setrec %u\n"),
+ (unsigned)bfd_getl16 (buf + 1));
+ cmdlen = 3;
+ break;
+ case DST__K_SRC_SETREC_L:
+ fprintf (file, _(" setrec %u\n"),
+ (unsigned)bfd_getl32 (buf + 1));
+ cmdlen = 5;
+ break;
+ case DST__K_SRC_SETLNUM_W:
+ fprintf (file, _(" setlnum %u\n"),
+ (unsigned)bfd_getl16 (buf + 1));
+ cmdlen = 3;
+ break;
+ case DST__K_SRC_SETLNUM_L:
+ fprintf (file, _(" setlnum %u\n"),
+ (unsigned)bfd_getl32 (buf + 1));
+ cmdlen = 5;
+ break;
+ case DST__K_SRC_DEFLINES_W:
+ fprintf (file, _(" deflines %u\n"),
+ (unsigned)bfd_getl16 (buf + 1));
+ cmdlen = 3;
+ break;
+ case DST__K_SRC_DEFLINES_B:
+ fprintf (file, _(" deflines %u\n"), buf[1]);
+ cmdlen = 2;
+ break;
+ case DST__K_SRC_FORMFEED:
+ fprintf (file, _(" formfeed\n"));
+ cmdlen = 1;
+ break;
+ default:
+ fprintf (file, _(" *unhandled* cmd %u\n"), cmd);
+ break;
+ }
+ if (cmdlen == 0)
+ break;
+ len -= cmdlen;
+ buf += cmdlen;
+ }
+ buf = buf_orig;
+ }
+ break;
+ default:
+ fprintf (file, _("*unhandled* dst type %u\n"), type);
+ break;
+ }
+ free (buf);
+ }
+}
+
+static void
+evax_bfd_print_image (bfd *abfd, FILE *file)
+{
+ struct vms_eihd eihd;
+ const char *name;
+ unsigned int val;
+ unsigned int eiha_off;
+ unsigned int eihi_off;
+ unsigned int eihs_off;
+ unsigned int eisd_off;
+ unsigned int eihef_off = 0;
+ unsigned int eihnp_off = 0;
+ unsigned int dmt_vbn = 0;
+ unsigned int dmt_size = 0;
+ unsigned int dst_vbn = 0;
+ unsigned int dst_size = 0;
+ unsigned int gst_vbn = 0;
+ unsigned int gst_size = 0;
+ unsigned int eiaf_vbn = 0;
+ unsigned int eiaf_size = 0;
+ unsigned int eihvn_off;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)
+ || bfd_bread (&eihd, sizeof (eihd), abfd) != sizeof (eihd))
+ {
+ fprintf (file, _("cannot read EIHD\n"));
+ return;
+ }
+ fprintf (file, _("EIHD: (size: %u, nbr blocks: %u)\n"),
+ (unsigned)bfd_getl32 (eihd.size),
+ (unsigned)bfd_getl32 (eihd.hdrblkcnt));
+ fprintf (file, _(" majorid: %u, minorid: %u\n"),
+ (unsigned)bfd_getl32 (eihd.majorid),
+ (unsigned)bfd_getl32 (eihd.minorid));
+
+ val = (unsigned)bfd_getl32 (eihd.imgtype);
+ switch (val)
+ {
+ case EIHD__K_EXE:
+ name = _("executable");
+ break;
+ case EIHD__K_LIM:
+ name = _("linkable image");
+ break;
+ default:
+ name = _("unknown");
+ break;
+ }
+ fprintf (file, _(" image type: %u (%s)"), val, name);
+
+ val = (unsigned)bfd_getl32 (eihd.subtype);
+ switch (val)
+ {
+ case EIHD__C_NATIVE:
+ name = _("native");
+ break;
+ case EIHD__C_CLI:
+ name = _("CLI");
+ break;
+ default:
+ name = _("unknown");
+ break;
+ }
+ fprintf (file, _(", subtype: %u (%s)\n"), val, name);
+
+ eisd_off = bfd_getl32 (eihd.isdoff);
+ eiha_off = bfd_getl32 (eihd.activoff);
+ eihi_off = bfd_getl32 (eihd.imgidoff);
+ eihs_off = bfd_getl32 (eihd.symdbgoff);
+ fprintf (file, _(" offsets: isd: %u, activ: %u, symdbg: %u, "
+ "imgid: %u, patch: %u\n"),
+ eisd_off, eiha_off, eihs_off, eihi_off,
+ (unsigned)bfd_getl32 (eihd.patchoff));
+ fprintf (file, _(" fixup info rva: "));
+ bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.iafva));
+ fprintf (file, _(", symbol vector rva: "));
+ bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.symvva));
+ eihvn_off = bfd_getl32 (eihd.version_array_off);
+ fprintf (file, _("\n"
+ " version array off: %u\n"),
+ eihvn_off);
+ fprintf (file,
+ _(" img I/O count: %u, nbr channels: %u, req pri: %08x%08x\n"),
+ (unsigned)bfd_getl32 (eihd.imgiocnt),
+ (unsigned)bfd_getl32 (eihd.iochancnt),
+ (unsigned)bfd_getl32 (eihd.privreqs + 4),
+ (unsigned)bfd_getl32 (eihd.privreqs + 0));
+ val = (unsigned)bfd_getl32 (eihd.lnkflags);
+ fprintf (file, _(" linker flags: %08x:"), val);
+ if (val & EIHD__M_LNKDEBUG)
+ fprintf (file, " LNKDEBUG");
+ if (val & EIHD__M_LNKNOTFR)
+ fprintf (file, " LNKNOTFR");
+ if (val & EIHD__M_NOP0BUFS)
+ fprintf (file, " NOP0BUFS");
+ if (val & EIHD__M_PICIMG)
+ fprintf (file, " PICIMG");
+ if (val & EIHD__M_P0IMAGE)
+ fprintf (file, " P0IMAGE");
+ if (val & EIHD__M_DBGDMT)
+ fprintf (file, " DBGDMT");
+ if (val & EIHD__M_INISHR)
+ fprintf (file, " INISHR");
+ if (val & EIHD__M_XLATED)
+ fprintf (file, " XLATED");
+ if (val & EIHD__M_BIND_CODE_SEC)
+ fprintf (file, " BIND_CODE_SEC");
+ if (val & EIHD__M_BIND_DATA_SEC)
+ fprintf (file, " BIND_DATA_SEC");
+ if (val & EIHD__M_MKTHREADS)
+ fprintf (file, " MKTHREADS");
+ if (val & EIHD__M_UPCALLS)
+ fprintf (file, " UPCALLS");
+ if (val & EIHD__M_OMV_READY)
+ fprintf (file, " OMV_READY");
+ if (val & EIHD__M_EXT_BIND_SECT)
+ fprintf (file, " EXT_BIND_SECT");
+ fprintf (file, "\n");
+ fprintf (file, _(" ident: 0x%08x, sysver: 0x%08x, "
+ "match ctrl: %u, symvect_size: %u\n"),
+ (unsigned)bfd_getl32 (eihd.ident),
+ (unsigned)bfd_getl32 (eihd.sysver),
+ eihd.matchctl,
+ (unsigned)bfd_getl32 (eihd.symvect_size));
+ fprintf (file, _(" BPAGE: %u"),
+ (unsigned)bfd_getl32 (eihd.virt_mem_block_size));
+ if (val & (EIHD__M_OMV_READY | EIHD__M_EXT_BIND_SECT))
+ {
+ eihef_off = bfd_getl32 (eihd.ext_fixup_off);
+ eihnp_off = bfd_getl32 (eihd.noopt_psect_off);
+ fprintf (file, _(", ext fixup offset: %u, no_opt psect off: %u"),
+ eihef_off, eihnp_off);
+ }
+ fprintf (file, _(", alias: %u\n"), (unsigned)bfd_getl16 (eihd.alias));
+
+ if (eihvn_off != 0)
+ {
+ struct vms_eihvn eihvn;
+ unsigned int mask;
+ unsigned int j;
+
+ fprintf (file, _("system version array information:\n"));
+ if (bfd_seek (abfd, (file_ptr) eihvn_off, SEEK_SET)
+ || bfd_bread (&eihvn, sizeof (eihvn), abfd) != sizeof (eihvn))
+ {
+ fprintf (file, _("cannot read EIHVN header\n"));
+ return;
+ }
+ mask = bfd_getl32 (eihvn.subsystem_mask);
+ for (j = 0; j < 32; j++)
+ if (mask & (1 << j))
+ {
+ struct vms_eihvn_subversion ver;
+ if (bfd_bread (&ver, sizeof (ver), abfd) != sizeof (ver))
+ {
+ fprintf (file, _("cannot read EIHVN version\n"));
+ return;
+ }
+ fprintf (file, _(" %02u "), j);
+ switch (j)
+ {
+ case EIHVN__BASE_IMAGE_BIT:
+ fputs (_("BASE_IMAGE "), file);
+ break;
+ case EIHVN__MEMORY_MANAGEMENT_BIT:
+ fputs (_("MEMORY_MANAGEMENT"), file);
+ break;
+ case EIHVN__IO_BIT:
+ fputs (_("IO "), file);
+ break;
+ case EIHVN__FILES_VOLUMES_BIT:
+ fputs (_("FILES_VOLUMES "), file);
+ break;
+ case EIHVN__PROCESS_SCHED_BIT:
+ fputs (_("PROCESS_SCHED "), file);
+ break;
+ case EIHVN__SYSGEN_BIT:
+ fputs (_("SYSGEN "), file);
+ break;
+ case EIHVN__CLUSTERS_LOCKMGR_BIT:
+ fputs (_("CLUSTERS_LOCKMGR "), file);
+ break;
+ case EIHVN__LOGICAL_NAMES_BIT:
+ fputs (_("LOGICAL_NAMES "), file);
+ break;
+ case EIHVN__SECURITY_BIT:
+ fputs (_("SECURITY "), file);
+ break;
+ case EIHVN__IMAGE_ACTIVATOR_BIT:
+ fputs (_("IMAGE_ACTIVATOR "), file);
+ break;
+ case EIHVN__NETWORKS_BIT:
+ fputs (_("NETWORKS "), file);
+ break;
+ case EIHVN__COUNTERS_BIT:
+ fputs (_("COUNTERS "), file);
+ break;
+ case EIHVN__STABLE_BIT:
+ fputs (_("STABLE "), file);
+ break;
+ case EIHVN__MISC_BIT:
+ fputs (_("MISC "), file);
+ break;
+ case EIHVN__CPU_BIT:
+ fputs (_("CPU "), file);
+ break;
+ case EIHVN__VOLATILE_BIT:
+ fputs (_("VOLATILE "), file);
+ break;
+ case EIHVN__SHELL_BIT:
+ fputs (_("SHELL "), file);
+ break;
+ case EIHVN__POSIX_BIT:
+ fputs (_("POSIX "), file);
+ break;
+ case EIHVN__MULTI_PROCESSING_BIT:
+ fputs (_("MULTI_PROCESSING "), file);
+ break;
+ case EIHVN__GALAXY_BIT:
+ fputs (_("GALAXY "), file);
+ break;
+ default:
+ fputs (_("*unknown* "), file);
+ break;
+ }
+ fprintf (file, _(": %u.%u\n"),
+ (unsigned)bfd_getl16 (ver.major),
+ (unsigned)bfd_getl16 (ver.minor));
+ }
+ }
+
+ if (eiha_off != 0)
+ {
+ struct vms_eiha eiha;
+
+ if (bfd_seek (abfd, (file_ptr) eiha_off, SEEK_SET)
+ || bfd_bread (&eiha, sizeof (eiha), abfd) != sizeof (eiha))
+ {
+ fprintf (file, _("cannot read EIHA\n"));
+ return;
+ }
+ fprintf (file, _("Image activation: (size=%u)\n"),
+ (unsigned)bfd_getl32 (eiha.size));
+ fprintf (file, _(" First address : 0x%08x 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiha.tfradr1_h),
+ (unsigned)bfd_getl32 (eiha.tfradr1));
+ fprintf (file, _(" Second address: 0x%08x 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiha.tfradr2_h),
+ (unsigned)bfd_getl32 (eiha.tfradr2));
+ fprintf (file, _(" Third address : 0x%08x 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiha.tfradr3_h),
+ (unsigned)bfd_getl32 (eiha.tfradr3));
+ fprintf (file, _(" Fourth address: 0x%08x 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiha.tfradr4_h),
+ (unsigned)bfd_getl32 (eiha.tfradr4));
+ fprintf (file, _(" Shared image : 0x%08x 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiha.inishr_h),
+ (unsigned)bfd_getl32 (eiha.inishr));
+ }
+ if (eihi_off != 0)
+ {
+ struct vms_eihi eihi;
+
+ if (bfd_seek (abfd, (file_ptr) eihi_off, SEEK_SET)
+ || bfd_bread (&eihi, sizeof (eihi), abfd) != sizeof (eihi))
+ {
+ fprintf (file, _("cannot read EIHI\n"));
+ return;
+ }
+ fprintf (file, _("Image identification: (major: %u, minor: %u)\n"),
+ (unsigned)bfd_getl32 (eihi.majorid),
+ (unsigned)bfd_getl32 (eihi.minorid));
+ fprintf (file, _(" image name : %.*s\n"),
+ eihi.imgnam[0], eihi.imgnam + 1);
+ fprintf (file, _(" link time : %s\n"),
+ vms_time_to_str (eihi.linktime));
+ fprintf (file, _(" image ident : %.*s\n"),
+ eihi.imgid[0], eihi.imgid + 1);
+ fprintf (file, _(" linker ident : %.*s\n"),
+ eihi.linkid[0], eihi.linkid + 1);
+ fprintf (file, _(" image build ident: %.*s\n"),
+ eihi.imgbid[0], eihi.imgbid + 1);
+ }
+ if (eihs_off != 0)
+ {
+ struct vms_eihs eihs;
+
+ if (bfd_seek (abfd, (file_ptr) eihs_off, SEEK_SET)
+ || bfd_bread (&eihs, sizeof (eihs), abfd) != sizeof (eihs))
+ {
+ fprintf (file, _("cannot read EIHS\n"));
+ return;
+ }
+ fprintf (file, _("Image symbol & debug table: (major: %u, minor: %u)\n"),
+ (unsigned)bfd_getl32 (eihs.majorid),
+ (unsigned)bfd_getl32 (eihs.minorid));
+ dst_vbn = bfd_getl32 (eihs.dstvbn);
+ dst_size = bfd_getl32 (eihs.dstsize);
+ fprintf (file, _(" debug symbol table : vbn: %u, size: %u\n"),
+ dst_vbn, dst_size);
+ gst_vbn = bfd_getl32 (eihs.gstvbn);
+ gst_size = bfd_getl32 (eihs.gstsize);
+ fprintf (file, _(" global symbol table: vbn: %u, records: %u\n"),
+ gst_vbn, gst_size);
+ dmt_vbn = bfd_getl32 (eihs.dmtvbn);
+ dmt_size = bfd_getl32 (eihs.dmtsize);
+ fprintf (file, _(" debug module table : vbn: %u, size: %u\n"),
+ dmt_vbn, dmt_size);
+ }
+ while (eisd_off != 0)
+ {
+ struct vms_eisd eisd;
+ unsigned int len;
+
+ while (1)
+ {
+ if (bfd_seek (abfd, (file_ptr) eisd_off, SEEK_SET)
+ || bfd_bread (&eisd, sizeof (eisd), abfd) != sizeof (eisd))
+ {
+ fprintf (file, _("cannot read EISD\n"));
+ return;
+ }
+ len = (unsigned)bfd_getl32 (eisd.eisdsize);
+ if (len != (unsigned)-1)
+ break;
+
+ /* Next block. */
+ eisd_off = (eisd_off + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
+ }
+ fprintf (file, _("Image section descriptor: (major: %u, minor: %u, "
+ "size: %u, offset: %u)\n"),
+ (unsigned)bfd_getl32 (eisd.majorid),
+ (unsigned)bfd_getl32 (eisd.minorid),
+ len, eisd_off);
+ if (len == 0)
+ break;
+ fprintf (file, _(" section: base: 0x%08x%08x size: 0x%08x\n"),
+ (unsigned)bfd_getl32 (eisd.virt_addr + 4),
+ (unsigned)bfd_getl32 (eisd.virt_addr + 0),
+ (unsigned)bfd_getl32 (eisd.secsize));
+ val = (unsigned)bfd_getl32 (eisd.flags);
+ fprintf (file, _(" flags: 0x%04x"), val);
+ if (val & EISD__M_GBL)
+ fprintf (file, " GBL");
+ if (val & EISD__M_CRF)
+ fprintf (file, " CRF");
+ if (val & EISD__M_DZRO)
+ fprintf (file, " DZRO");
+ if (val & EISD__M_WRT)
+ fprintf (file, " WRT");
+ if (val & EISD__M_INITALCODE)
+ fprintf (file, " INITALCODE");
+ if (val & EISD__M_BASED)
+ fprintf (file, " BASED");
+ if (val & EISD__M_FIXUPVEC)
+ fprintf (file, " FIXUPVEC");
+ if (val & EISD__M_RESIDENT)
+ fprintf (file, " RESIDENT");
+ if (val & EISD__M_VECTOR)
+ fprintf (file, " VECTOR");
+ if (val & EISD__M_PROTECT)
+ fprintf (file, " PROTECT");
+ if (val & EISD__M_LASTCLU)
+ fprintf (file, " LASTCLU");
+ if (val & EISD__M_EXE)
+ fprintf (file, " EXE");
+ if (val & EISD__M_NONSHRADR)
+ fprintf (file, " NONSHRADR");
+ if (val & EISD__M_QUAD_LENGTH)
+ fprintf (file, " QUAD_LENGTH");
+ if (val & EISD__M_ALLOC_64BIT)
+ fprintf (file, " ALLOC_64BIT");
+ fprintf (file, "\n");
+ if (val & EISD__M_FIXUPVEC)
+ {
+ eiaf_vbn = bfd_getl32 (eisd.vbn);
+ eiaf_size = bfd_getl32 (eisd.secsize);
+ }
+ fprintf (file, _(" vbn: %u, pfc: %u, matchctl: %u type: %u ("),
+ (unsigned)bfd_getl32 (eisd.vbn),
+ eisd.pfc, eisd.matchctl, eisd.type);
+ switch (eisd.type)
+ {
+ case EISD__K_NORMAL:
+ fputs (_("NORMAL"), file);
+ break;
+ case EISD__K_SHRFXD:
+ fputs (_("SHRFXD"), file);
+ break;
+ case EISD__K_PRVFXD:
+ fputs (_("PRVFXD"), file);
+ break;
+ case EISD__K_SHRPIC:
+ fputs (_("SHRPIC"), file);
+ break;
+ case EISD__K_PRVPIC:
+ fputs (_("PRVPIC"), file);
+ break;
+ case EISD__K_USRSTACK:
+ fputs (_("USRSTACK"), file);
+ break;
+ default:
+ fputs (_("*unknown*"), file);
+ break;
+ }
+ fputs (_(")\n"), file);
+ if (val & EISD__M_GBL)
+ fprintf (file, _(" ident: 0x%08x, name: %.*s\n"),
+ (unsigned)bfd_getl32 (eisd.ident),
+ eisd.gblnam[0], eisd.gblnam + 1);
+ eisd_off += len;
+ }
+
+ if (dmt_vbn != 0)
+ {
+ if (bfd_seek (abfd, (file_ptr) (dmt_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET))
+ {
+ fprintf (file, _("cannot read DMT\n"));
+ return;
+ }
+
+ fprintf (file, _("Debug module table:\n"));
+
+ while (dmt_size > 0)
+ {
+ struct vms_dmt_header dmth;
+ unsigned int count;
+
+ if (bfd_bread (&dmth, sizeof (dmth), abfd) != sizeof (dmth))
+ {
+ fprintf (file, _("cannot read DMT header\n"));
+ return;
+ }
+ count = bfd_getl16 (dmth.psect_count);
+ fprintf (file,
+ _(" module address: 0x%08x, size: 0x%08x, (%u psect)\n"),
+ (unsigned)bfd_getl32 (dmth.modbeg),
+ (unsigned)bfd_getl32 (dmth.size), count);
+ dmt_size -= sizeof (dmth);
+ while (count > 0)
+ {
+ struct vms_dmt_psect dmtp;
+
+ if (bfd_bread (&dmtp, sizeof (dmtp), abfd) != sizeof (dmtp))
+ {
+ fprintf (file, _("cannot read DMT psect\n"));
+ return;
+ }
+ fprintf (file, _(" psect start: 0x%08x, length: %u\n"),
+ (unsigned)bfd_getl32 (dmtp.start),
+ (unsigned)bfd_getl32 (dmtp.length));
+ count--;
+ dmt_size -= sizeof (dmtp);
+ }
+ }
+ }
+
+ if (dst_vbn != 0)
+ {
+ if (bfd_seek (abfd, (file_ptr) (dst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET))
+ {
+ fprintf (file, _("cannot read DST\n"));
+ return;
+ }
+
+ evax_bfd_print_dst (abfd, dst_size, file);
+ }
+ if (gst_vbn != 0)
+ {
+ if (bfd_seek (abfd, (file_ptr) (gst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET))
+ {
+ fprintf (file, _("cannot read GST\n"));
+ return;
+ }
+
+ fprintf (file, _("Global symbol table:\n"));
+ evax_bfd_print_eobj (abfd, file);
+ }
+ if (eiaf_vbn != 0)
+ {
+ unsigned char *buf;
+ struct vms_eiaf *eiaf;
+ unsigned int qrelfixoff;
+ unsigned int lrelfixoff;
+ unsigned int qdotadroff;
+ unsigned int ldotadroff;
+ unsigned int shrimgcnt;
+ unsigned int shlstoff;
+ unsigned int codeadroff;
+ unsigned int lpfixoff;
+ unsigned int chgprtoff;
+
+ buf = bfd_malloc (eiaf_size);
+
+ if (bfd_seek (abfd, (file_ptr) (eiaf_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET)
+ || bfd_bread (buf, eiaf_size, abfd) != eiaf_size)
+ {
+ fprintf (file, _("cannot read EIHA\n"));
+ free (buf);
+ return;
+ }
+ eiaf = (struct vms_eiaf *)buf;
+ fprintf (file,
+ _("Image activator fixup: (major: %u, minor: %u)\n"),
+ (unsigned)bfd_getl32 (eiaf->majorid),
+ (unsigned)bfd_getl32 (eiaf->minorid));
+ fprintf (file, _(" iaflink : 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (eiaf->iaflink + 0),
+ (unsigned)bfd_getl32 (eiaf->iaflink + 4));
+ fprintf (file, _(" fixuplnk: 0x%08x %08x\n"),
+ (unsigned)bfd_getl32 (eiaf->fixuplnk + 0),
+ (unsigned)bfd_getl32 (eiaf->fixuplnk + 4));
+ fprintf (file, _(" size : %u\n"),
+ (unsigned)bfd_getl32 (eiaf->size));
+ fprintf (file, _(" flags: 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiaf->flags));
+ qrelfixoff = bfd_getl32 (eiaf->qrelfixoff);
+ lrelfixoff = bfd_getl32 (eiaf->lrelfixoff);
+ fprintf (file, _(" qrelfixoff: %5u, lrelfixoff: %5u\n"),
+ qrelfixoff, lrelfixoff);
+ qdotadroff = bfd_getl32 (eiaf->qdotadroff);
+ ldotadroff = bfd_getl32 (eiaf->ldotadroff);
+ fprintf (file, _(" qdotadroff: %5u, ldotadroff: %5u\n"),
+ qdotadroff, ldotadroff);
+ codeadroff = bfd_getl32 (eiaf->codeadroff);
+ lpfixoff = bfd_getl32 (eiaf->lpfixoff);
+ fprintf (file, _(" codeadroff: %5u, lpfixoff : %5u\n"),
+ codeadroff, lpfixoff);
+ chgprtoff = bfd_getl32 (eiaf->chgprtoff);
+ fprintf (file, _(" chgprtoff : %5u\n"), chgprtoff);
+ shrimgcnt = bfd_getl32 (eiaf->shrimgcnt);
+ shlstoff = bfd_getl32 (eiaf->shlstoff);
+ fprintf (file, _(" shlstoff : %5u, shrimgcnt : %5u\n"),
+ shlstoff, shrimgcnt);
+ fprintf (file, _(" shlextra : %5u, permctx : %5u\n"),
+ (unsigned)bfd_getl32 (eiaf->shlextra),
+ (unsigned)bfd_getl32 (eiaf->permctx));
+ fprintf (file, _(" base_va : 0x%08x\n"),
+ (unsigned)bfd_getl32 (eiaf->base_va));
+ fprintf (file, _(" lppsbfixoff: %5u\n"),
+ (unsigned)bfd_getl32 (eiaf->lppsbfixoff));
+
+ if (shlstoff)
+ {
+ struct vms_shl *shl = (struct vms_shl *)(buf + shlstoff);
+ unsigned int j;
+
+ fprintf (file, _(" Shareable images:\n"));
+ for (j = 0; j < shrimgcnt; j++, shl++)
+ {
+ fprintf (file,
+ _(" %u: size: %u, flags: 0x%02x, name: %.*s\n"),
+ j, shl->size, shl->flags,
+ shl->imgnam[0], shl->imgnam + 1);
+ }
+ }
+ if (qrelfixoff != 0)
+ {
+ fprintf (file, _(" quad-word relocation fixups:\n"));
+ evax_bfd_print_relocation_records (file, buf + qrelfixoff, 8);
+ }
+ if (lrelfixoff != 0)
+ {
+ fprintf (file, _(" long-word relocation fixups:\n"));
+ evax_bfd_print_relocation_records (file, buf + lrelfixoff, 4);
+ }
+ if (qdotadroff != 0)
+ {
+ fprintf (file, _(" quad-word .address reference fixups:\n"));
+ evax_bfd_print_address_fixups (file, buf + qdotadroff);
+ }
+ if (ldotadroff != 0)
+ {
+ fprintf (file, _(" long-word .address reference fixups:\n"));
+ evax_bfd_print_address_fixups (file, buf + ldotadroff);
+ }
+ if (codeadroff != 0)
+ {
+ fprintf (file, _(" Code Address Reference Fixups:\n"));
+ evax_bfd_print_reference_fixups (file, buf + codeadroff);
+ }
+ if (lpfixoff != 0)
+ {
+ fprintf (file, _(" Linkage Pairs Referece Fixups:\n"));
+ evax_bfd_print_reference_fixups (file, buf + lpfixoff);
+ }
+ if (chgprtoff)
+ {
+ unsigned int count = (unsigned)bfd_getl32 (buf + chgprtoff);
+ struct vms_eicp *eicp = (struct vms_eicp *)(buf + chgprtoff + 4);
+ unsigned int j;
+
+ fprintf (file, _(" Change Protection (%u entries):\n"), count);
+ for (j = 0; j < count; j++, eicp++)
+ {
+ unsigned int prot = bfd_getl32 (eicp->newprt);
+ fprintf (file,
+ _(" base: 0x%08x %08x, size: 0x%08x, prot: 0x%08x "),
+ (unsigned)bfd_getl32 (eicp->baseva + 4),
+ (unsigned)bfd_getl32 (eicp->baseva + 0),
+ (unsigned)bfd_getl32 (eicp->size),
+ (unsigned)bfd_getl32 (eicp->newprt));
+ switch (prot)
+ {
+ case PRT__C_NA:
+ fprintf (file, "NA");
+ break;
+ case PRT__C_RESERVED:
+ fprintf (file, "RES");
+ break;
+ case PRT__C_KW:
+ fprintf (file, "KW");
+ break;
+ case PRT__C_KR:
+ fprintf (file, "KR");
+ break;
+ case PRT__C_UW:
+ fprintf (file, "UW");
+ break;
+ case PRT__C_EW:
+ fprintf (file, "EW");
+ break;
+ case PRT__C_ERKW:
+ fprintf (file, "ERKW");
+ break;
+ case PRT__C_ER:
+ fprintf (file, "ER");
+ break;
+ case PRT__C_SW:
+ fprintf (file, "SW");
+ break;
+ case PRT__C_SREW:
+ fprintf (file, "SREW");
+ break;
+ case PRT__C_SRKW:
+ fprintf (file, "SRKW");
+ break;
+ case PRT__C_SR:
+ fprintf (file, "SR");
+ break;
+ case PRT__C_URSW:
+ fprintf (file, "URSW");
+ break;
+ case PRT__C_UREW:
+ fprintf (file, "UREW");
+ break;
+ case PRT__C_URKW:
+ fprintf (file, "URKW");
+ break;
+ case PRT__C_UR:
+ fprintf (file, "UR");
+ break;
+ default:
+ fputs ("??", file);
+ break;
+ }
+ fputc ('\n', file);
+ }
+ }
+ free (buf);
+ }
+}
+
+static bfd_boolean
+vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr)
+{
+ FILE *file = (FILE *)ptr;
+
+ if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC))
+ evax_bfd_print_image (abfd, file);
+ else
+ {
+ if (bfd_seek (abfd, 0, SEEK_SET))
+ return FALSE;
+ evax_bfd_print_eobj (abfd, file);
+ }
+ return TRUE;
+}
+\f
+/* Linking. */
+
+/* Slurp an ordered set of VMS object records. */
+
+static bfd_boolean
+alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
+{
+ asection *cur_section;
+ file_ptr cur_offset;
+ asection *dst_section;
+ file_ptr dst_offset;
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ return FALSE;
+
+ PRIV (image_autoextend) = FALSE;
+
+ cur_section = NULL;
+ cur_offset = 0;
+
+ dst_section = PRIV (dst_section);
+ dst_offset = 0;
+ if (info)
+ {
+ if (info->strip == strip_all || info->strip == strip_debugger)
+ {
+ dst_offset = 0;
+ dst_section = NULL;
+ }
+ else if (dst_section)
+ {
+ dst_offset = dst_section->output_offset;
+ dst_section = dst_section->output_section;
+ }
+ }
+
+ while (1)
+ {
+ int type;
+ bfd_boolean res;
+
+ type = _bfd_vms_get_object_record (abfd);
+ if (type < 0)
+ {
+ vms_debug2 ((2, "next_record failed\n"));
+ return FALSE;
+ }
+ switch (type)
+ {
+ case EOBJ__C_ETIR:
+ PRIV (image_section) = cur_section;
+ PRIV (image_offset) = cur_offset;
+ res = _bfd_vms_slurp_etir (abfd, info);
+ cur_section = PRIV (image_section);
+ cur_offset = PRIV (image_offset);
+ break;
+ case EOBJ__C_EDBG:
+ case EOBJ__C_ETBT:
+ if (dst_section == NULL)
+ continue;
+ PRIV (image_section) = dst_section;
+ PRIV (image_offset) = dst_offset;
+ PRIV (image_autoextend) = TRUE;
+ res = _bfd_vms_slurp_etir (abfd, info);
+ PRIV (image_autoextend) = FALSE;
+ dst_offset = PRIV (image_offset);
+ break;
+ case EOBJ__C_EEOM:
+ return TRUE;
+ default:
+ continue;
+ }
+ if (!res)
+ {
+ vms_debug2 ((2, "slurp eobj type %d failed\n", type));
+ return FALSE;
+ }
+ }
+}
+
+static int
+alpha_vms_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+/* Add a linkage pair fixup at address SECT + OFFSET to SHLIB. */
+
+static void
+alpha_vms_add_fixup_lp (struct bfd_link_info *info, bfd *src, bfd *shlib)
+{
+ struct alpha_vms_shlib_el *sl;
+ asection *sect = PRIV2 (src, image_section);
+ file_ptr offset = PRIV2 (src, image_offset);
+
+ sl = &VEC_EL (alpha_vms_link_hash (info)->shrlibs,
+ struct alpha_vms_shlib_el, PRIV2 (shlib, shr_index));
+ sl->has_fixups = TRUE;
+ VEC_APPEND_EL (sl->lp, bfd_vma,
+ sect->output_section->vma + sect->output_offset + offset);
+}
+
+static void
+alpha_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib)
+{
+ struct alpha_vms_shlib_el *sl;
+ asection *sect = PRIV2 (src, image_section);
+ file_ptr offset = PRIV2 (src, image_offset);
+
+ sl = &VEC_EL (alpha_vms_link_hash (info)->shrlibs,
+ struct alpha_vms_shlib_el, PRIV2 (shlib, shr_index));
+ sl->has_fixups = TRUE;
+ VEC_APPEND_EL (sl->ca, bfd_vma,
+ sect->output_section->vma + sect->output_offset + offset);
+}
+
+static void
+alpha_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src,
+ bfd *shlib, bfd_vma vec)
+{
+ struct alpha_vms_shlib_el *sl;
+ struct alpha_vms_vma_ref *r;
+ asection *sect = PRIV2 (src, image_section);
+ file_ptr offset = PRIV2 (src, image_offset);
+
+ sl = &VEC_EL (alpha_vms_link_hash (info)->shrlibs,
+ struct alpha_vms_shlib_el, PRIV2 (shlib, shr_index));
+ sl->has_fixups = TRUE;
+ r = VEC_APPEND (sl->qr, struct alpha_vms_vma_ref);
+ r->vma = sect->output_section->vma + sect->output_offset + offset;
+ r->ref = vec;
+}
+
+static void
+alpha_vms_add_lw_fixup (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ unsigned int shr ATTRIBUTE_UNUSED,
+ bfd_vma vec ATTRIBUTE_UNUSED)
+{
+ abort ();
+}
+
+#if 0
+static void
+alpha_vms_add_qw_fixup (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ unsigned int shr ATTRIBUTE_UNUSED,
+ bfd_vma vec ATTRIBUTE_UNUSED)
+{
+ abort ();
+}
+#endif
+
+static void
+alpha_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+}
+
+static void
+alpha_vms_add_qw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+}
+
+static struct bfd_hash_entry *
+alpha_vms_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
+{
+ struct alpha_vms_link_hash_entry *ret =
+ (struct alpha_vms_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = ((struct alpha_vms_link_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct alpha_vms_link_hash_entry)));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct alpha_vms_link_hash_entry *)
+ _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+
+ ret->sym = NULL;
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an Alpha/VMS link hash table. */
+
+static struct bfd_link_hash_table *
+alpha_vms_bfd_link_hash_table_create (bfd *abfd)
+{
+ struct alpha_vms_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct alpha_vms_link_hash_table);
+
+ ret = (struct alpha_vms_link_hash_table *) bfd_malloc (amt);
+ if (ret == NULL)
+ return NULL;
+ if (!_bfd_link_hash_table_init (&ret->root, abfd,
+ alpha_vms_link_hash_newfunc,
+ sizeof (struct alpha_vms_link_hash_entry)))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ VEC_INIT (ret->shrlibs);
+ ret->fixup = NULL;
+
+ return &ret->root;
+}
+
+static bfd_boolean
+alpha_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
+{
+ unsigned int i;
+
+ for (i = 0; i < PRIV (gsd_sym_count); i++)
+ {
+ struct vms_symbol_entry *e = PRIV (syms)[i];
+ struct alpha_vms_link_hash_entry *h;
+ asymbol sym;
+
+ if (!alpha_vms_convert_symbol (abfd, e, &sym))
+ return FALSE;
+
+ if ((e->flags & EGSY__V_DEF) && abfd->selective_search)
+ {
+ /* In selective_search mode, only add definition that are
+ required. */
+ h = (struct alpha_vms_link_hash_entry *)bfd_link_hash_lookup
+ (info->hash, sym.name, FALSE, FALSE, FALSE);
+ if (h == NULL || h->root.type != bfd_link_hash_undefined)
+ continue;
+ }
+ else
+ h = NULL;
+
+ if (_bfd_generic_link_add_one_symbol
+ (info, abfd, sym.name, sym.flags, sym.section, sym.value,
+ NULL, FALSE, FALSE, (struct bfd_link_hash_entry **)&h) == FALSE)
+ return FALSE;
+
+ if ((e->flags & EGSY__V_DEF)
+ && h->sym == NULL
+ && abfd->xvec == info->output_bfd->xvec)
+ h->sym = e;
+ }
+
+ if (abfd->flags & DYNAMIC)
+ {
+ struct alpha_vms_shlib_el *shlib;
+
+ /* We do not want to include any of the sections in a dynamic
+ object in the output file. See comment in elflink.c. */
+ bfd_section_list_clear (abfd);
+
+ shlib = VEC_APPEND (alpha_vms_link_hash (info)->shrlibs,
+ struct alpha_vms_shlib_el);
+ shlib->abfd = abfd;
+ VEC_INIT (shlib->ca);
+ VEC_INIT (shlib->lp);
+ VEC_INIT (shlib->qr);
+ PRIV (shr_index) = VEC_COUNT (alpha_vms_link_hash (info)->shrlibs) - 1;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
+{
+ int pass;
+ struct bfd_link_hash_entry **pundef;
+ struct bfd_link_hash_entry **next_pundef;
+
+ /* We only accept VMS libraries. */
+ if (info->output_bfd->xvec != abfd->xvec)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
+
+ /* The archive_pass field in the archive itself is used to
+ initialize PASS, since we may search the same archive multiple
+ times. */
+ pass = ++abfd->archive_pass;
+
+ /* Look through the list of undefined symbols. */
+ for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef)
+ {
+ struct bfd_link_hash_entry *h;
+ file_ptr file_offset;
+ bfd *element;
+ bfd *orig_element;
+
+ h = *pundef;
+ next_pundef = &(*pundef)->u.undef.next;
+
+ /* When a symbol is defined, it is not necessarily removed from
+ the list. */
+ if (h->type != bfd_link_hash_undefined
+ && h->type != bfd_link_hash_common)
+ {
+ /* Remove this entry from the list, for general cleanliness
+ and because we are going to look through the list again
+ if we search any more libraries. We can't remove the
+ entry if it is the tail, because that would lose any
+ entries we add to the list later on. */
+ if (*pundef != info->hash->undefs_tail)
+ {
+ *pundef = *next_pundef;
+ next_pundef = pundef;
+ }
+ continue;
+ }
+
+ /* Look for this symbol in the archive hash table. */
+ file_offset = _bfd_vms_lib_find_symbol (abfd, h->root.string);
+ if (file_offset == 0)
+ {
+ /* Nothing in this slot. */
+ continue;
+ }
+
+ element = bfd_get_elt_at_index (abfd, file_offset);
+ if (element == NULL)
+ return FALSE;
+
+ if (element->archive_pass == -1 || element->archive_pass == pass)
+ continue;
+
+ if (! bfd_check_format (element, bfd_object))
+ {
+ element->archive_pass = -1;
+ return FALSE;
+ }
+
+ orig_element = element;
+ if (bfd_is_thin_archive (abfd))
+ {
+ element = _bfd_vms_lib_get_imagelib_file (element);
+ if (element == NULL || !bfd_check_format (element, bfd_object))
+ {
+ orig_element->archive_pass = -1;
+ return FALSE;
+ }
+ }
+
+ /* Unlike the generic linker, we know that this element provides
+ a definition for an undefined symbol and we know that we want
+ to include it. We don't need to check anything. */
+ if (! (*info->callbacks->add_archive_element) (info, element,
+ h->root.string))
+ return FALSE;
+ if (! alpha_vms_link_add_object_symbols (element, info))
+ return FALSE;
+
+ orig_element->archive_pass = pass;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+alpha_vms_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
+{
+ switch (bfd_get_format (abfd))
+ {
+ case bfd_object:
+ vms_debug2 ((2, "vms_link_add_symbols for object %s\n",
+ abfd->filename));
+ return alpha_vms_link_add_object_symbols (abfd, info);
+ break;
+ case bfd_archive:
+ vms_debug2 ((2, "vms_link_add_symbols for archive %s\n",
+ abfd->filename));
+ return alpha_vms_link_add_archive_symbols (abfd, info);
+ break;
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
+}
+
+static bfd_boolean
+alpha_vms_build_fixups (struct bfd_link_info *info)
+{
+ struct alpha_vms_link_hash_table *t = alpha_vms_link_hash (info);
+ unsigned char *content;
+ unsigned int i;
+ unsigned int sz = 0;
+ unsigned int lp_sz = 0;
+ unsigned int ca_sz = 0;
+ unsigned int qr_sz = 0;
+ unsigned int shrimg_cnt = 0;
+ struct vms_eiaf *eiaf;
+ unsigned int off;
+ asection *sec;
+
+ /* Shared libraries. */
+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
+ {
+ struct alpha_vms_shlib_el *shlib;
+
+ shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
+
+ if (!shlib->has_fixups)
+ continue;
+
+ shrimg_cnt++;
+
+ if (VEC_COUNT (shlib->ca) > 0)
+ {
+ /* Header + entries. */
+ ca_sz += 8;
+ ca_sz += VEC_COUNT (shlib->ca) * 4;
+ }
+ if (VEC_COUNT (shlib->lp) > 0)
+ {
+ /* Header + entries. */
+ lp_sz += 8;
+ lp_sz += VEC_COUNT (shlib->lp) * 4;
+ }
+ if (VEC_COUNT (shlib->qr) > 0)
+ {
+ /* Header + entries. */
+ qr_sz += 8;
+ qr_sz += VEC_COUNT (shlib->qr) * 8;
+ }
+ }
+ /* Add markers. */
+ if (ca_sz > 0)
+ ca_sz += 8;
+ if (lp_sz > 0)
+ lp_sz += 8;
+ if (qr_sz > 0)
+ qr_sz += 8;
+
+ /* Finish now if there is no content. */
+ if (ca_sz + lp_sz + qr_sz == 0)
+ return TRUE;
+
+ /* Allocate section content (round-up size) */
+ sz = sizeof (struct vms_eiaf) + shrimg_cnt * sizeof (struct vms_shl)
+ + ca_sz + lp_sz + qr_sz;
+ sz = (sz + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1);
+ content = bfd_zalloc (info->output_bfd, sz);
+ if (content == NULL)
+ return FALSE;
+
+ sec = alpha_vms_link_hash (info)->fixup;
+ sec->contents = content;
+ sec->size = sz;
+
+ eiaf = (struct vms_eiaf *)content;
+ off = sizeof (struct vms_eiaf);
+ bfd_putl32 (0, eiaf->majorid);
+ bfd_putl32 (0, eiaf->minorid);
+ bfd_putl32 (0, eiaf->iaflink);
+ bfd_putl32 (0, eiaf->fixuplnk);
+ bfd_putl32 (sizeof (struct vms_eiaf), eiaf->size);
+ bfd_putl32 (0, eiaf->flags);
+ bfd_putl32 (0, eiaf->qrelfixoff);
+ bfd_putl32 (0, eiaf->lrelfixoff);
+ bfd_putl32 (0, eiaf->qdotadroff);
+ bfd_putl32 (0, eiaf->ldotadroff);
+ bfd_putl32 (0, eiaf->codeadroff);
+ bfd_putl32 (0, eiaf->lpfixoff);
+ bfd_putl32 (0, eiaf->chgprtoff);
+ bfd_putl32 (shrimg_cnt ? off : 0, eiaf->shlstoff);
+ bfd_putl32 (shrimg_cnt, eiaf->shrimgcnt);
+ bfd_putl32 (0, eiaf->shlextra);
+ bfd_putl32 (0, eiaf->permctx);
+ bfd_putl32 (0, eiaf->base_va);
+ bfd_putl32 (0, eiaf->lppsbfixoff);
+
+ if (shrimg_cnt)
+ {
+ shrimg_cnt = 0;
+
+ /* Write shl. */
+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
+ {
+ struct alpha_vms_shlib_el *shlib;
+ struct vms_shl *shl;
+
+ shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
+
+ if (!shlib->has_fixups)
+ continue;
+
+ /* Renumber shared images. */
+ PRIV2 (shlib->abfd, shr_index) = shrimg_cnt++;
+
+ shl = (struct vms_shl *)(content + off);
+ bfd_putl32 (0, shl->baseva);
+ bfd_putl32 (0, shl->shlptr);
+ bfd_putl32 (0, shl->ident);
+ bfd_putl32 (0, shl->permctx);
+ shl->size = sizeof (struct vms_shl);
+ bfd_putl16 (0, shl->fill_1);
+ shl->flags = 0;
+ bfd_putl32 (0, shl->icb);
+ shl->imgnam[0] = strlen (PRIV2 (shlib->abfd, hdr_data.hdr_t_name));
+ memcpy (shl->imgnam + 1, PRIV2 (shlib->abfd, hdr_data.hdr_t_name),
+ shl->imgnam[0]);
+
+ off += sizeof (struct vms_shl);
+ }
+
+ /* CA fixups. */
+ if (ca_sz != 0)
+ {
+ bfd_putl32 (off, eiaf->codeadroff);
+
+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
+ {
+ struct alpha_vms_shlib_el *shlib;
+ unsigned int j;
+
+ shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
+
+ if (VEC_COUNT (shlib->ca) == 0)
+ continue;
+
+ bfd_putl32 (VEC_COUNT (shlib->ca), content + off);
+ bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4);
+ off += 8;
+
+ for (j = 0; j < VEC_COUNT (shlib->ca); j++)
+ {
+ bfd_putl32 (VEC_EL (shlib->ca, bfd_vma, j) - t->base_addr,
+ content + off);
+ off += 4;
+ }
+ }
+
+ bfd_putl32 (0, content + off);
+ bfd_putl32 (0, content + off + 4);
+ off += 8;
+ }
+
+ /* LP fixups. */
+ if (lp_sz != 0)
+ {
+ bfd_putl32 (off, eiaf->lpfixoff);
+
+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
+ {
+ struct alpha_vms_shlib_el *shlib;
+ unsigned int j;
+
+ shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
+
+ if (VEC_COUNT (shlib->lp) == 0)
+ continue;
+
+ bfd_putl32 (VEC_COUNT (shlib->lp), content + off);
+ bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4);
+ off += 8;
+
+ for (j = 0; j < VEC_COUNT (shlib->lp); j++)
+ {
+ bfd_putl32 (VEC_EL (shlib->lp, bfd_vma, j) - t->base_addr,
+ content + off);
+ off += 4;
+ }
+ }
+
+ bfd_putl32 (0, content + off);
+ bfd_putl32 (0, content + off + 4);
+ off += 8;
+ }
+
+ /* QR fixups. */
+ if (qr_sz != 0)
+ {
+ bfd_putl32 (off, eiaf->qdotadroff);
+
+ for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
+ {
+ struct alpha_vms_shlib_el *shlib;
+ unsigned int j;
+
+ shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
+
+ if (VEC_COUNT (shlib->qr) == 0)
+ continue;
+
+ bfd_putl32 (VEC_COUNT (shlib->qr), content + off);
+ bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4);
+ off += 8;
+
+ for (j = 0; j < VEC_COUNT (shlib->qr); j++)
+ {
+ struct alpha_vms_vma_ref *r;
+ r = &VEC_EL (shlib->qr, struct alpha_vms_vma_ref, j);
+ bfd_putl32 (r->vma - t->base_addr, content + off);
+ bfd_putl32 (r->ref, content + off + 4);
+ off += 8;
+ }
+ }
+
+ bfd_putl32 (0, content + off);
+ bfd_putl32 (0, content + off + 4);
+ off += 8;
+ }
+
+ /* CA fixups. */
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
+{
+ asection *o;
+ struct bfd_link_order *p;
+ bfd *sub;
+ asection *fixupsec;
+ bfd_vma base_addr;
+ bfd_vma last_addr;
+
+ bfd_get_outsymbols (abfd) = NULL;
+ bfd_get_symcount (abfd) = 0;
+
+ /* Mark all sections which will be included in the output file. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
+ if (p->type == bfd_indirect_link_order)
+ p->u.indirect.section->linker_mark = TRUE;
+
+#if 0
+ /* Handle all the link order information for the sections. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ printf ("For section %s (at 0x%08x, flags=0x%08x):\n",
+ o->name, (unsigned)o->vma, (unsigned)o->flags);
+
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
+ {
+ printf (" at 0x%08x - 0x%08x: ",
+ (unsigned)p->offset, (unsigned)(p->offset + p->size - 1));
+ switch (p->type)
+ {
+ case bfd_section_reloc_link_order:
+ case bfd_symbol_reloc_link_order:
+ printf (" section/symbol reloc\n");
+ break;
+ case bfd_indirect_link_order:
+ printf (" section %s of %s\n",
+ p->u.indirect.section->name,
+ p->u.indirect.section->owner->filename);
+ break;
+ case bfd_data_link_order:
+ printf (" explicit data\n");
+ break;
+ default:
+ printf (" *unknown* type %u\n", p->type);
+ break;
+ }
+ }
+ }
+#endif
+
+ /* Find entry point. */
+ if (bfd_get_start_address (abfd) == 0)
+ {
+ bfd *startbfd = NULL;
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ /* Consider only VMS object files. */
+ if (sub->xvec != abfd->xvec)
+ continue;
+
+ if (!PRIV2 (sub, eom_data).eom_has_transfer)
+ continue;
+ if ((PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR) && startbfd)
+ continue;
+ if (startbfd != NULL
+ && !(PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR))
+ {
+ (*info->callbacks->einfo)
+ (_("%P: multiple entry points: in modules %B and %B\n"),
+ startbfd, sub);
+ continue;
+ }
+ startbfd = sub;
+ }
+
+ if (startbfd)
+ {
+ unsigned int ps_idx = PRIV2 (startbfd, eom_data).eom_l_psindx;
+ bfd_vma tfradr = PRIV2 (startbfd, eom_data).eom_l_tfradr;
+ asection *sec;
+
+ sec = PRIV2 (startbfd, sections)[ps_idx];
+
+ bfd_set_start_address
+ (abfd, sec->output_section->vma + sec->output_offset + tfradr);
+ }
+ }
+
+ /* Allocate content. */
+ base_addr = (bfd_vma)-1;
+ last_addr = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->flags & SEC_HAS_CONTENTS)
+ {
+ o->contents = bfd_alloc (abfd, o->size);
+ if (o->contents == NULL)
+ return FALSE;
+ }
+ if (o->flags & SEC_LOAD)
+ {
+ if (o->vma < base_addr)
+ base_addr = o->vma;
+ if (o->vma + o->size > last_addr)
+ last_addr = o->vma + o->size;
+ }
+ }
+
+ fixupsec = bfd_make_section_anyway_with_flags
+ (info->output_bfd, "$FIXUP$",
+ SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
+ if (fixupsec == NULL)
+ return FALSE;
+ last_addr = (last_addr + 0xffff) & ~0xffff;
+ fixupsec->vma = last_addr;
+
+ alpha_vms_link_hash (info)->fixup = fixupsec;
+ alpha_vms_link_hash (info)->base_addr = base_addr;
+
+ /* Read all sections from the inputs. */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ if (sub->flags & DYNAMIC)
+ {
+ alpha_vms_create_eisd_for_shared (abfd, sub);
+ continue;
+ }
+
+ if (!alpha_vms_read_sections_content (sub, info))
+ return FALSE;
+ }
+
+ /* Handle all the link order information for the sections. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
+ {
+ switch (p->type)
+ {
+ case bfd_section_reloc_link_order:
+ case bfd_symbol_reloc_link_order:
+ abort ();
+ return FALSE;
+ case bfd_indirect_link_order:
+ /* Already done. */
+ break;
+ default:
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ return FALSE;
+ break;
+ }
+ }
+ }
+
+ /* Compute fixups. */
+ if (!alpha_vms_build_fixups (info))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Read the contents of a section.
+ buf points to a buffer of buf_size bytes to be filled with
+ section data (starting at offset into section) */
+
+static bfd_boolean
+alpha_vms_get_section_contents (bfd *abfd, asection *section,
+ void *buf, file_ptr offset,
+ bfd_size_type count)
+{
+ asection *sec;
+
+ /* Image are easy. */
+ if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC))
+ return _bfd_generic_get_section_contents (abfd, section,
+ buf, offset, count);
+
+ /* Safety check. */
+ if (offset + count < count
+ || offset + count > section->size)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
+ /* Alloc in memory and read ETIRs. */
+ BFD_ASSERT (section->contents == NULL);
+
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ BFD_ASSERT (sec->contents == NULL);
+
+ if (sec->size != 0 && (sec->flags & SEC_HAS_CONTENTS))
+ {
+ sec->contents = bfd_alloc (abfd, sec->size);
+ if (sec->contents == NULL)
+ return FALSE;
+ }
+ }
+ if (!alpha_vms_read_sections_content (abfd, NULL))
+ return FALSE;
+ for (sec = abfd->sections; sec; sec = sec->next)
+ if (section->contents)
+ section->flags |= SEC_IN_MEMORY;
+ memcpy (buf, section->contents + offset, count);
+ return TRUE;
+}
+
+
+/* Set the format of a file being written. */
+
+static bfd_boolean
+alpha_vms_mkobject (bfd * abfd)
+{
+ const bfd_arch_info_type *arch;
+
+ vms_debug2 ((1, "alpha_vms_mkobject (%p)\n", abfd));
+
+ if (!vms_initialize (abfd))
+ return FALSE;
+
+ PRIV (recwr.buf) = bfd_alloc (abfd, MAX_OUTREC_SIZE);
+ if (PRIV (recwr.buf) == NULL)
+ return FALSE;
+
+ 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. */
+
+/* Called when the BFD is being closed to do any necessary cleanup. */
+
+static bfd_boolean
+vms_close_and_cleanup (bfd * abfd)
+{
+ vms_debug2 ((1, "vms_close_and_cleanup (%p)\n", abfd));
+
+ if (abfd == NULL || abfd->tdata.any == NULL)
+ return TRUE;
+
+ if (abfd->format == bfd_archive)
+ {
+ bfd_release (abfd, abfd->tdata.any);
+ abfd->tdata.any = NULL;
+ return TRUE;
+ }
+
+ if (PRIV (recrd.buf) != NULL)
+ free (PRIV (recrd.buf));
+
+ if (PRIV (sections) != NULL)
+ free (PRIV (sections));
+
+ 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;
+}
+
+/* Called when a new section is created. */
+
+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_debug2 ((1, "vms_new_section_hook (%p, [%d]%s), count %d\n",
+ abfd, section->index, section->name, section_count));
+
+ bfd_set_section_alignment (abfd, section, 0);
+
+ if (section_count > PRIV (section_count))
+ {
+ amt = section_count;
+ amt *= sizeof (asection *);
+ PRIV (sections) = bfd_realloc_or_free (PRIV (sections), amt);
+ if (PRIV (sections) == NULL)
+ return FALSE;
+ PRIV (section_count) = section_count;
+ }
+
+ vms_debug2 ((6, "section_count: %d\n", PRIV (section_count)));
+
+ PRIV (sections)[section->index] = section;
+
+ vms_debug2 ((7, "%d: %s\n", section->index, section->name));
+
+ amt = sizeof (struct vms_section_data_struct);
+ section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
+ if (section->used_by_bfd == NULL)
+ return FALSE;
+
+ if (strcmp (bfd_get_section_name (abfd, section), "$DST$") == 0)
+ PRIV (dst_section) = section;
+
+ /* Create the section symbol. */
+ return _bfd_generic_new_section_hook (abfd, section);
+}
+
+/* Part 4.5, symbols. */
+
+/* Print symbol to file according to how. how is one of
+ bfd_print_symbol_name just print the name
+ bfd_print_symbol_more print more (???)
+ bfd_print_symbol_all print all we know, which is not much right now :-). */
+
+static void
+vms_print_symbol (bfd * abfd,
+ void * file,
+ asymbol *symbol,
+ bfd_print_symbol_type how)
+{
+ vms_debug2 ((1, "vms_print_symbol (%p, %p, %p, %d)\n",
+ abfd, file, symbol, how));
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ case bfd_print_symbol_more:
+ fprintf ((FILE *)file," %s", symbol->name);
+ break;
+
+ case bfd_print_symbol_all:
+ {
+ const char *section_name = symbol->section->name;
+
+ bfd_print_symbol_vandf (abfd, file, symbol);
+
+ fprintf ((FILE *) file," %-8s %s", section_name, symbol->name);
+ }
+ break;
+ }
+}
+
+/* Return information about symbol in ret.
+
+ fill type, value and name
+ type:
+ A absolute
+ B bss segment symbol
+ C common symbol
+ D data segment symbol
+ f filename
+ t a static function symbol
+ T text segment symbol
+ U undefined
+ - debug. */
+
+static void
+vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED,
+ asymbol *symbol,
+ symbol_info *ret)
+{
+ asection *sec;
+
+ vms_debug2 ((1, "vms_get_symbol_info (%p, %p, %p)\n", abfd, symbol, ret));
+
+ sec = symbol->section;
+
+ if (ret == NULL)
+ return;
+
+ if (sec == 0)
+ ret->type = 'U';
+ else if (bfd_is_com_section (sec))
+ ret->type = 'C';
+ else if (bfd_is_abs_section (sec))
+ ret->type = 'A';
+ else if (bfd_is_und_section (sec))
+ ret->type = 'U';
+ else if (bfd_is_ind_section (sec))
+ ret->type = 'I';
+ else if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
+ ret->type = 'T';
+ else if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ ret->type = 'D';
+ else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ ret->type = 'B';
+ else
+ ret->type = '-';
+
+ if (ret->type != 'U')
+ ret->value = symbol->value + symbol->section->vma;
+ else
+ ret->value = 0;
+ ret->name = symbol->name;
+}
+
+/* Return TRUE if the given symbol sym in the BFD abfd is
+ a compiler generated local label, else return FALSE. */
+
+static bfd_boolean
+vms_bfd_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
+ const char *name)
+{
+ vms_debug2 ((1, "vms_bfd_is_local_label_name (%p, %s)\n", abfd, name));
+ return name[0] == '$';
+}
+\f
+/* Part 4.7, writing an object file. */
+
+/* Sets the contents of the section section in BFD abfd to the data starting
+ in memory at LOCATION. The data is written to the output section starting
+ at offset offset for count bytes.
+
+ Normally TRUE is returned, else FALSE. Possible error returns are:
+ o bfd_error_no_contents - The output section does not have the
+ SEC_HAS_CONTENTS attribute, so nothing can be written to it.
+ o and some more too */
+
+static bfd_boolean
+_bfd_vms_set_section_contents (bfd * abfd,
+ asection *section,
+ const void * location,
+ file_ptr offset,
+ bfd_size_type count)
+{
+ 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;
+}
+
+/* Set the architecture and machine type in BFD abfd to arch and mach.
+ Find the correct pointer to a structure and insert it into the arch_info
+ pointer. */
+
+static bfd_boolean
+alpha_vms_set_arch_mach (bfd *abfd,
+ enum bfd_architecture arch, unsigned long mach)
+{
+ if (arch != bfd_arch_alpha
+ && arch != bfd_arch_unknown)
+ return FALSE;
+
+ return bfd_default_set_arch_mach (abfd, arch, mach);
+}
+
+/* Set section VMS flags. Clear NO_FLAGS and set FLAGS. */
+
+void
+bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec, flagword no_flags, flagword flags)
+{
+ vms_section_data (sec)->no_flags = no_flags;
+ vms_section_data (sec)->flags = flags;
+}
+
+struct vms_private_data_struct *
+bfd_vms_get_data (bfd *abfd)
+{
+ return (struct vms_private_data_struct *)abfd->tdata.any;
+}
+
+#define vms_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
+#define vms_bfd_link_just_syms _bfd_generic_link_just_syms
+#define vms_bfd_copy_link_hash_symbol_type \
+ _bfd_generic_copy_link_hash_symbol_type
+#define vms_bfd_is_group_section bfd_generic_is_group_section
+#define vms_bfd_discard_group bfd_generic_discard_group
+#define vms_section_already_linked _bfd_generic_section_already_linked
+#define vms_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define vms_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
+
+#define vms_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
+#define vms_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define vms_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
+#define vms_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
+#define vms_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+#define vms_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+
+/* Symbols table. */
+#define alpha_vms_make_empty_symbol _bfd_generic_make_empty_symbol
+#define alpha_vms_bfd_is_target_special_symbol \
+ ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
+#define alpha_vms_print_symbol vms_print_symbol
+#define alpha_vms_get_symbol_info vms_get_symbol_info
+#define alpha_vms_read_minisymbols _bfd_generic_read_minisymbols
+#define alpha_vms_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+#define alpha_vms_get_lineno _bfd_nosymbols_get_lineno
+#define alpha_vms_find_inliner_info _bfd_nosymbols_find_inliner_info
+#define alpha_vms_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define alpha_vms_find_nearest_line _bfd_vms_find_nearest_dst_line
+#define alpha_vms_bfd_is_local_label_name vms_bfd_is_local_label_name
+
+/* Generic table. */
+#define alpha_vms_close_and_cleanup vms_close_and_cleanup
+#define alpha_vms_bfd_free_cached_info vms_bfd_free_cached_info
+#define alpha_vms_new_section_hook vms_new_section_hook
+#define alpha_vms_set_section_contents _bfd_vms_set_section_contents
+#define alpha_vms_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
+
+#define alpha_vms_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+
+#define alpha_vms_bfd_relax_section bfd_generic_relax_section
+#define alpha_vms_bfd_gc_sections bfd_generic_gc_sections
+#define alpha_vms_bfd_merge_sections bfd_generic_merge_sections
+#define alpha_vms_bfd_is_group_section bfd_generic_is_group_section
+#define alpha_vms_bfd_discard_group bfd_generic_discard_group
+#define alpha_vms_section_already_linked \
+ _bfd_generic_section_already_linked
+
+#define alpha_vms_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define alpha_vms_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
+#define alpha_vms_bfd_link_just_syms _bfd_generic_link_just_syms
+#define alpha_vms_bfd_copy_link_hash_symbol_type \
+ _bfd_generic_copy_link_hash_symbol_type
+
+#define alpha_vms_bfd_link_split_section _bfd_generic_link_split_section
+
+#define alpha_vms_get_dynamic_symtab_upper_bound \
+ _bfd_nodynamic_get_dynamic_symtab_upper_bound
+#define alpha_vms_canonicalize_dynamic_symtab \
+ _bfd_nodynamic_canonicalize_dynamic_symtab
+#define alpha_vms_get_dynamic_reloc_upper_bound \
+ _bfd_nodynamic_get_dynamic_reloc_upper_bound
+#define alpha_vms_canonicalize_dynamic_reloc \
+ _bfd_nodynamic_canonicalize_dynamic_reloc
+
+const bfd_target vms_alpha_vec =
+{
+ "vms-alpha", /* Name. */
+ bfd_target_evax_flavour,
+ BFD_ENDIAN_LITTLE, /* Data byte order is little. */
+ BFD_ENDIAN_LITTLE, /* Header byte order is little. */
+
+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
+ | WP_TEXT | D_PAGED), /* Object flags. */
+ (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_READONLY | SEC_CODE | SEC_DATA
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */
+ 0, /* symbol_leading_char. */
+ ' ', /* ar_pad_char. */
+ 15, /* ar_max_namelen. */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16,
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16,
+
+ {_bfd_dummy_target, alpha_vms_object_p, /* bfd_check_format. */
+ _bfd_vms_lib_alpha_archive_p, _bfd_dummy_target},
+ {bfd_false, alpha_vms_mkobject, /* bfd_set_format. */
+ _bfd_vms_lib_mkarchive, bfd_false},
+ {bfd_false, alpha_vms_write_object_contents, /* bfd_write_contents. */
+ _bfd_vms_lib_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (alpha_vms),
+ BFD_JUMP_TABLE_COPY (vms),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
+ BFD_JUMP_TABLE_SYMBOLS (alpha_vms),
+ BFD_JUMP_TABLE_RELOCS (alpha_vms),
+ BFD_JUMP_TABLE_WRITE (alpha_vms),
+ BFD_JUMP_TABLE_LINK (alpha_vms),
+ BFD_JUMP_TABLE_DYNAMIC (alpha_vms),
+
+ NULL,
+
+ (PTR) 0
+};
+++ /dev/null
-/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and
- EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007, 2009 Free Software Foundation, Inc.
-
- GSD record handling functions
- EGSD record handling functions
-
- Go and read the openVMS linker manual (esp. appendix B)
- if you don't know what's going on here :-)
-
- Written by Klaus K"ampf (kkaempf@rmi.de)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
-
-#include "sysdep.h"
-#include "bfd.h"
-#include "bfdlink.h"
-#include "libbfd.h"
-
-#include "vms.h"
-
-/* Typical sections for vax object files. */
-
-#define VAX_CODE_NAME "$CODE"
-#define VAX_DATA_NAME "$DATA"
-#define VAX_ADDRESS_DATA_NAME "$ADDRESS_DATA"
-
-/* Typical sections for evax object files. */
-
-#define EVAX_ABS_NAME "$ABS$"
-#define EVAX_CODE_NAME "$CODE$"
-#define EVAX_LINK_NAME "$LINK$"
-#define EVAX_DATA_NAME "$DATA$"
-#define EVAX_BSS_NAME "$BSS$"
-#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$"
-#define EVAX_READONLY_NAME "$READONLY$"
-#define EVAX_LITERAL_NAME "$LITERAL$"
-#define EVAX_LITERALS_NAME "$LITERALS"
-#define EVAX_COMMON_NAME "$COMMON$"
-#define EVAX_LOCAL_NAME "$LOCAL$"
-
-struct sec_flags_struct
-{
- char *name; /* Name of section. */
- int vflags_always;
- flagword flags_always; /* Flags we set always. */
- int vflags_hassize;
- flagword flags_hassize; /* Flags we set if the section has a size > 0. */
-};
-
-/* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible. */
-
-static struct sec_flags_struct vax_section_flags[] =
- {
- { VAX_CODE_NAME,
- (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
- (SEC_CODE),
- (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
- (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { VAX_DATA_NAME,
- (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
- (SEC_DATA),
- (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { VAX_ADDRESS_DATA_NAME,
- (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
- (SEC_DATA | SEC_READONLY),
- (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
- { NULL,
- (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
- (SEC_DATA),
- (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
- };
-
-/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible. */
-
-static struct sec_flags_struct evax_section_flags[] =
- {
- { EVAX_ABS_NAME,
- (EGPS_S_V_SHR),
- (SEC_DATA),
- (EGPS_S_V_SHR),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { EVAX_CODE_NAME,
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
- (SEC_CODE),
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
- (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { EVAX_LITERAL_NAME,
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
- (SEC_DATA | SEC_READONLY),
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
- { EVAX_LINK_NAME,
- (EGPS_S_V_REL | EGPS_S_V_RD),
- (SEC_DATA | SEC_READONLY),
- (EGPS_S_V_REL | EGPS_S_V_RD),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
- { EVAX_DATA_NAME,
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
- (SEC_DATA),
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { EVAX_BSS_NAME,
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
- (SEC_NO_FLAGS),
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
- (SEC_IN_MEMORY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { EVAX_READONLYADDR_NAME,
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
- (SEC_DATA | SEC_READONLY),
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
- { EVAX_READONLY_NAME,
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
- (SEC_DATA | SEC_READONLY),
- (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
- { EVAX_LOCAL_NAME,
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
- (SEC_DATA),
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
- { 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),
- (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
- (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
- };
-
-/* Retrieve bfd section flags by name and size. */
-
-static flagword
-vms_secflag_by_name (bfd *abfd,
- struct sec_flags_struct *section_flags,
- char *name,
- int hassize)
-{
- int i = 0;
-
- while (section_flags[i].name != NULL)
- {
- if ((PRIV (is_vax)?
- strcasecmp (name, section_flags[i].name):
- strcmp (name, section_flags[i].name)) == 0)
- {
- if (hassize)
- return section_flags[i].flags_hassize;
- else
- return section_flags[i].flags_always;
- }
- i++;
- }
- if (hassize)
- return section_flags[i].flags_hassize;
- return section_flags[i].flags_always;
-}
-
-/* Retrieve vms section flags by name and size. */
-
-static flagword
-vms_esecflag_by_name (struct sec_flags_struct *section_flags,
- char *name,
- int hassize)
-{
- int i = 0;
-
- while (section_flags[i].name != NULL)
- {
- if (strcmp (name, section_flags[i].name) == 0)
- {
- if (hassize)
- return section_flags[i].vflags_hassize;
- else
- return section_flags[i].vflags_always;
- }
- i++;
- }
- if (hassize)
- return section_flags[i].vflags_hassize;
- return section_flags[i].vflags_always;
-}
-
-#if VMS_DEBUG
-
-struct flagdescstruct { const 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", EGSY_S_V_NORM },
- { NULL, 0 }
-};
-
-static char *flag2str (struct flagdescstruct *, flagword);
-
-/* Convert flag to printable string. */
-
-static char *
-flag2str (struct flagdescstruct * flagdesc, flagword flags)
-{
- static char res[64];
- int next = 0;
-
- res[0] = 0;
- while (flagdesc->name != NULL)
- {
- if ((flags & flagdesc->value) != 0)
- {
- if (next)
- strcat (res, ",");
- else
- next = 1;
- strcat (res, flagdesc->name);
- }
- flagdesc++;
- }
- return res;
-}
-#endif
-
-/* Input routines. */
-
-static int register_universal_symbol (bfd *abfd, asymbol *symbol,
- int vms_flags);
-
-/* Process GSD/EGSD record
- return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_gsd (bfd * abfd, int objtype)
-{
- int gsd_type, gsd_size;
- asection *section;
- unsigned char *vms_rec;
- flagword new_flags, old_flags;
- char *name;
- asymbol *symbol;
- vms_symbol_entry *entry;
- unsigned long base_addr;
- unsigned long align_addr;
- static unsigned int psect_idx = 0;
-
-#if VMS_DEBUG
- vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype);
-#endif
-
- switch (objtype)
- {
- case EOBJ_S_C_EGSD:
- PRIV (vms_rec) += 8; /* Skip type, size, l_temp. */
- PRIV (rec_size) -= 8;
- break;
- case OBJ_S_C_GSD:
- PRIV (vms_rec) += 1;
- PRIV (rec_size) -= 1;
- break;
- default:
- return -1;
- }
-
- /* Calculate base address for each section. */
- base_addr = 0L;
-
- abfd->symcount = 0;
-
- while (PRIV (rec_size) > 0)
- {
- vms_rec = PRIV (vms_rec);
-
- if (objtype == OBJ_S_C_GSD)
- gsd_type = vms_rec[0];
- else
- {
- _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
- gsd_type += EVAX_OFFSET;
- }
-
-#if VMS_DEBUG
- vms_debug (3, "gsd_type %d\n", gsd_type);
-#endif
-
- switch (gsd_type)
- {
- case GSD_S_C_PSC:
- {
- /* Program section definition. */
- asection *old_section = 0;
-
-#if VMS_DEBUG
- vms_debug (4, "GSD_S_C_PSC\n");
-#endif
- /* If this section isn't a bfd section. */
- if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1)))
- {
- /* Check for temporary section from TIR record. */
- if (psect_idx < PRIV (section_count))
- old_section = PRIV (sections)[psect_idx];
- else
- old_section = 0;
- }
-
- name = _bfd_vms_save_counted_string (vms_rec + 8);
- section = bfd_make_section (abfd, name);
- if (!section)
- {
- (*_bfd_error_handler) (_("bfd_make_section (%s) failed"),
- name);
- return -1;
- }
- old_flags = bfd_getl16 (vms_rec + 2);
- section->size = bfd_getl32 (vms_rec + 4); /* allocation */
- new_flags = vms_secflag_by_name (abfd, vax_section_flags, name,
- section->size > 0);
- if (old_flags & EGPS_S_V_REL)
- new_flags |= SEC_RELOC;
- if (old_flags & GPS_S_M_OVR)
- new_flags |= SEC_IS_COMMON;
- if (!bfd_set_section_flags (abfd, section, new_flags))
- {
- (*_bfd_error_handler)
- (_("bfd_set_section_flags (%s, %x) failed"),
- name, new_flags);
- return -1;
- }
- section->alignment_power = vms_rec[1];
- align_addr = (1 << section->alignment_power);
- if ((base_addr % align_addr) != 0)
- base_addr += (align_addr - (base_addr % align_addr));
- section->vma = (bfd_vma)base_addr;
- base_addr += section->size;
-
- /* Global section is common symbol. */
- if (old_flags & GPS_S_M_GBL)
- {
- entry = _bfd_vms_enter_symbol (abfd, name);
- if (entry == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
- symbol = entry->symbol;
-
- symbol->value = 0;
- symbol->section = section;
- symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON);
- }
-
- /* Copy saved contents if old_section set. */
- if (old_section != 0)
- {
- section->contents = old_section->contents;
- if (section->size < old_section->size)
- {
- (*_bfd_error_handler)
- (_("Size mismatch section %s=%lx, %s=%lx"),
- old_section->name,
- (unsigned long) old_section->size,
- section->name,
- (unsigned long) section->size);
- return -1;
- }
- else if (section->size > old_section->size)
- {
- section->contents = bfd_realloc (old_section->contents,
- section->size);
- if (section->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
- }
- }
- else
- {
- section->contents = bfd_zmalloc (section->size);
- if (section->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
- }
-#if VMS_DEBUG
- vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ",
- section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
- vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
- section->size, section->vma, section->contents);
-#endif
-
- gsd_size = vms_rec[8] + 9;
-
- psect_idx++;
- }
- break;
-
- case GSD_S_C_EPM:
- case GSD_S_C_EPMW:
-#if VMS_DEBUG
- vms_debug (4, "gsd epm\n");
-#endif
- /* Fall through. */
- case GSD_S_C_SYM:
- case GSD_S_C_SYMW:
- {
- int name_offset = 0, value_offset = 0;
-
- /* Symbol specification (definition or reference). */
-#if VMS_DEBUG
- vms_debug (4, "GSD_S_C_SYM(W)\n");
-#endif
- old_flags = bfd_getl16 (vms_rec + 2);
- new_flags = BSF_NO_FLAGS;
-
- if (old_flags & GSY_S_M_WEAK)
- new_flags |= BSF_WEAK;
-
- switch (gsd_type)
- {
- case GSD_S_C_EPM:
- name_offset = 11;
- value_offset = 5;
- new_flags |= BSF_FUNCTION;
- break;
- case GSD_S_C_EPMW:
- name_offset = 12;
- value_offset = 6;
- new_flags |= BSF_FUNCTION;
- break;
- case GSD_S_C_SYM:
- if (old_flags & GSY_S_M_DEF) /* Symbol definition. */
- name_offset = 9;
- else
- name_offset = 4;
- value_offset = 5;
- break;
- case GSD_S_C_SYMW:
- if (old_flags & GSY_S_M_DEF) /* Symbol definition. */
- name_offset = 10;
- else
- name_offset = 5;
- value_offset = 6;
- break;
- }
-
- /* Save symbol in vms_symbol_table. */
- entry = _bfd_vms_enter_symbol
- (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset));
- if (entry == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
- symbol = entry->symbol;
-
- if (old_flags & GSY_S_M_DEF)
- {
- /* Symbol definition. */
- int psect;
-
- symbol->value = bfd_getl32 (vms_rec + value_offset);
- if ((gsd_type == GSD_S_C_SYMW)
- || (gsd_type == GSD_S_C_EPMW))
- psect = bfd_getl16 (vms_rec + value_offset - 2);
- else
- psect = vms_rec[value_offset-1];
-
- symbol->section = (asection *)(unsigned long)psect;
-#if VMS_DEBUG
- vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount,
- symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags));
-#endif
- }
- else
- {
- /* Symbol reference. */
-#if VMS_DEBUG
- vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
- symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
-#endif
- symbol->section = (asection *)(unsigned long)-1;
- }
-
- gsd_size = vms_rec[name_offset] + name_offset + 1;
- symbol->flags = new_flags;
- }
-
- break;
-
- case GSD_S_C_PRO:
- case GSD_S_C_PROW:
-#if VMS_DEBUG
- vms_debug (4, "gsd pro\n");
-#endif
- break;
- case GSD_S_C_IDC:
-#if VMS_DEBUG
- vms_debug (4, "gsd idc\n");
-#endif
- break;
- case GSD_S_C_ENV:
-#if VMS_DEBUG
- vms_debug (4, "gsd env\n");
-#endif
- break;
- case GSD_S_C_LSY:
-#if VMS_DEBUG
- vms_debug (4, "gsd lsy\n");
-#endif
- break;
- case GSD_S_C_LEPM:
-#if VMS_DEBUG
- vms_debug (4, "gsd lepm\n");
-#endif
- break;
- case GSD_S_C_LPRO:
-#if VMS_DEBUG
- vms_debug (4, "gsd lpro\n");
-#endif
- break;
- case GSD_S_C_SPSC:
-#if VMS_DEBUG
- vms_debug (4, "gsd spsc\n");
-#endif
- break;
- case GSD_S_C_SYMV:
-#if VMS_DEBUG
- vms_debug (4, "gsd symv\n");
-#endif
- break;
- case GSD_S_C_EPMV:
-#if VMS_DEBUG
- vms_debug (4, "gsd epmv\n");
-#endif
- break;
- case GSD_S_C_PROV:
-#if VMS_DEBUG
- vms_debug (4, "gsd prov\n");
-#endif
- break;
-
- case EGSD_S_C_PSC + EVAX_OFFSET:
- {
- /* Program section definition. */
- name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG);
- section = bfd_make_section (abfd, name);
- if (!section)
- return -1;
- old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS);
- section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC);
- new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
- section->size > 0);
- if (old_flags & EGPS_S_V_REL)
- new_flags |= SEC_RELOC;
- if (!bfd_set_section_flags (abfd, section, new_flags))
- return -1;
- section->alignment_power = vms_rec[EGPS_S_B_ALIGN];
- align_addr = (1 << section->alignment_power);
- if ((base_addr % align_addr) != 0)
- base_addr += (align_addr - (base_addr % align_addr));
- section->vma = (bfd_vma)base_addr;
- base_addr += section->size;
- section->contents = bfd_zmalloc (section->size);
- if (section->contents == NULL)
- return -1;
- section->filepos = (unsigned int)-1;
-#if VMS_DEBUG
- vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ",
- section->index, name, old_flags, flag2str(gpsflagdesc, old_flags));
- vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
- section->size, section->vma, section->contents);
-#endif
- }
- break;
-
- case EGSD_S_C_SYM + EVAX_OFFSET:
- {
- /* Global symbol specification (definition or reference). */
- symbol = bfd_make_empty_symbol (abfd);
- if (symbol == 0)
- return -1;
-
- old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS);
- new_flags = BSF_NO_FLAGS;
-
- if (old_flags & EGSY_S_V_WEAK)
- new_flags |= BSF_WEAK;
-
- if (old_flags & EGSY_S_V_DEF)
- {
- /* Symbol definition. */
- if (old_flags & EGSY_S_V_NORM)
- new_flags |= BSF_FUNCTION;
- symbol->name =
- _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG);
- symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE);
- symbol->section =
- (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX);
-#if VMS_DEBUG
- vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n",
- abfd->symcount, symbol->name, (long)symbol->section,
- old_flags, flag2str (gsyflagdesc, old_flags));
-#endif
- }
- else
- {
- /* Symbol reference. */
- symbol->name =
- _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG);
-#if VMS_DEBUG
- vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n",
- abfd->symcount, symbol->name, old_flags,
- flag2str (gsyflagdesc, old_flags));
-#endif
- symbol->section = (asection *)(unsigned long)-1;
- }
-
- symbol->flags = new_flags;
-
- /* Register symbol in VMS symbol table. */
- entry = (vms_symbol_entry *) bfd_hash_lookup
- (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE);
-
- if (entry == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
-
- if (entry->symbol != NULL)
- {
- /* FIXME ?, DEC C generates this. */
-#if VMS_DEBUG
- vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name);
-#endif
- }
- else
- {
- entry->symbol = symbol;
- PRIV (gsd_sym_count)++;
- abfd->symcount++;
- }
- }
- break;
-
- case EGSD_S_C_SYMG + EVAX_OFFSET:
- {
- /* Universal symbol specification (definition). */
- symbol = bfd_make_empty_symbol (abfd);
- if (symbol == 0)
- return -1;
-
- old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS);
- new_flags = BSF_NO_FLAGS;
-
- if (old_flags & EGSY_S_V_WEAK)
- new_flags |= BSF_WEAK;
-
- if (old_flags & EGSY_S_V_DEF) /* symbol definition */
- {
- if (old_flags & EGSY_S_V_NORM)
- new_flags |= BSF_FUNCTION;
-
- symbol->name =
- _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG);
-
- /* For BSF_FUNCTION symbols, the entry point is in LP_1
- and the descriptor in LP_2. For other symbols, the
- unique value is in LP_2. */
- symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2);
-
- /* Adding this offset is necessary in order for GDB to
- read the DWARF-2 debug info from shared libraries. */
- if (abfd->flags & DYNAMIC
- && strstr (symbol->name, "$DWARF2.DEBUG") != 0)
- symbol->value += PRIV (symvva);
- }
- else /* symbol reference */
- (*_bfd_error_handler) ("Invalid EGST reference");
-
- symbol->flags = new_flags;
-
- if (register_universal_symbol (abfd, symbol, old_flags) < 0)
- return -1;
-
- /* Make a second symbol for the entry point. */
- if (symbol->flags & BSF_FUNCTION)
- {
- asymbol *en_sym;
-
- name = bfd_alloc (abfd, strlen (symbol->name) + 5);
-
- en_sym = bfd_make_empty_symbol (abfd);
- if (en_sym == 0)
- return -1;
-
- strcpy (name, symbol->name);
- strcat (name, "..en");
-
- en_sym->name = name;
- en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);
-
- if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
- return -1;
- }
- }
- break;
-
- case EGSD_S_C_IDC + EVAX_OFFSET:
- break;
-
- default:
- (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
- bfd_set_error (bfd_error_bad_value);
- return -1;
- }
-
- PRIV (rec_size) -= gsd_size;
- PRIV (vms_rec) += gsd_size;
- }
-
- if (abfd->symcount > 0)
- abfd->flags |= HAS_SYMS;
-
- return 0;
-}
-
-/* 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. */
-
-int
-_bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
-{
- asection *section;
- asymbol *symbol;
- unsigned int symnum;
- int last_index = -1;
- 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);
-#endif
-
- /* Output sections. */
- section = abfd->sections;
-#if VMS_DEBUG
- vms_debug (3, "%d sections found\n", abfd->section_count);
-#endif
-
- /* Egsd is quadword aligned. */
- _bfd_vms_output_alignment (abfd, 8);
-
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
- _bfd_vms_output_long (abfd, 0);
- /* Prepare output for subrecords. */
- _bfd_vms_output_push (abfd);
-
- while (section != 0)
- {
-#if VMS_DEBUG
- 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)
- {
- _bfd_vms_output_pop (abfd);
- _bfd_vms_output_end (abfd);
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
- _bfd_vms_output_long (abfd, 0);
- /* Prepare output for subrecords. */
- _bfd_vms_output_push (abfd);
- }
-
- /* Create dummy sections to keep consecutive indices. */
- while (section->index - last_index > 1)
- {
-#if VMS_DEBUG
- vms_debug (3, "index %d, last %d\n", section->index, last_index);
-#endif
- _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
- _bfd_vms_output_short (abfd, 0);
- _bfd_vms_output_short (abfd, 0);
- _bfd_vms_output_long (abfd, 0);
- sprintf (dummy_name, ".DUMMY%02d", last_index);
- _bfd_vms_output_counted (abfd, dummy_name);
- _bfd_vms_output_flush (abfd);
- last_index++;
- }
-
- /* Don't know if this is necessary for the linker but for now it keeps
- vms_slurp_gsd happy */
- sname = (char *)section->name;
- if (*sname == '.')
- {
- sname++;
- if ((*sname == 't') && (strcmp (sname, "text") == 0))
- sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME;
- else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
- sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME;
- else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
- sname = EVAX_BSS_NAME;
- else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
- sname = EVAX_LINK_NAME;
- else if ((*sname == 'r') && (strcmp (sname, "rdata") == 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))
- sname = EVAX_LOCAL_NAME;
- }
- else
- sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ);
-
- _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
- _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
-
- if (bfd_is_com_section (section))
- new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD
- | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
- else
- new_flags = vms_esecflag_by_name (evax_section_flags, sname,
- section->size > 0);
-
- /* Modify them as directed. */
- if (section->flags & SEC_READONLY)
- new_flags &= ~EGPS_S_V_WRT;
-
- new_flags |= vms_section_data (section)->vflags & 0xffff;
- new_flags &=
- ~((vms_section_data (section)->vflags >> EGPS_S_V_NO_SHIFT) & 0xffff);
-
-#if VMS_DEBUG
- vms_debug (3, "sec flags %x\n", section->flags);
- vms_debug (3, "new_flags %x, _raw_size %d\n", new_flags, section->size);
-#endif
-
- _bfd_vms_output_short (abfd, new_flags);
- _bfd_vms_output_long (abfd, (unsigned long) section->size);
- _bfd_vms_output_counted (abfd, sname);
- _bfd_vms_output_flush (abfd);
-
- last_index = section->index;
-done:
- section = section->next;
- }
-
- /* Output symbols. */
-#if VMS_DEBUG
- vms_debug (3, "%d symbols found\n", abfd->symcount);
-#endif
-
- bfd_set_start_address (abfd, (bfd_vma) -1);
-
- for (symnum = 0; symnum < abfd->symcount; symnum++)
- {
- char *hash;
-
- symbol = abfd->outsymbols[symnum];
- if (*(symbol->name) == '_')
- {
- if (strcmp (symbol->name, "__main") == 0)
- bfd_set_start_address (abfd, (bfd_vma)symbol->value);
- }
- old_flags = symbol->flags;
-
- if (old_flags & BSF_FILE)
- continue;
-
- if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */
- && !bfd_is_und_section (symbol->section) /* and not xref... */
- && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */
- && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
- continue;
-
- /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */
- if (_bfd_vms_output_check (abfd, 80) < 0)
- {
- _bfd_vms_output_pop (abfd);
- _bfd_vms_output_end (abfd);
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
- _bfd_vms_output_long (abfd, 0);
- /* Prepare output for subrecords. */
- _bfd_vms_output_push (abfd);
- }
-
- _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1);
-
- /* Data type, alignment. */
- _bfd_vms_output_short (abfd, 0);
-
- new_flags = 0;
-
- if (old_flags & BSF_WEAK)
- new_flags |= EGSY_S_V_WEAK;
- if (bfd_is_com_section (symbol->section)) /* .comm */
- new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
-
- if (old_flags & BSF_FUNCTION)
- {
- new_flags |= EGSY_S_V_NORM;
- new_flags |= EGSY_S_V_REL;
- }
- if (old_flags & BSF_GLOBAL)
- {
- new_flags |= EGSY_S_V_DEF;
- if (!bfd_is_abs_section (symbol->section))
- new_flags |= EGSY_S_V_REL;
- }
- _bfd_vms_output_short (abfd, new_flags);
-
- if (old_flags & BSF_GLOBAL)
- {
- /* Symbol definition. */
- uquad code_address = 0;
- unsigned long ca_psindx = 0;
- unsigned long psindx;
-
- if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
- {
- asymbol *sym;
-
- if (bfd_get_flavour (abfd) == bfd_target_evax_flavour)
- sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
- else
- sym = (asymbol *)symbol->udata.p;
- code_address = sym->value;
- ca_psindx = sym->section->index;
- }
- if (bfd_is_abs_section (symbol->section))
- psindx = abs_section_index;
- else
- psindx = symbol->section->index;
-
- _bfd_vms_output_quad (abfd, symbol->value);
- _bfd_vms_output_quad (abfd, code_address);
- _bfd_vms_output_long (abfd, ca_psindx);
- _bfd_vms_output_long (abfd, psindx);
- }
- hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ);
- _bfd_vms_output_counted (abfd, hash);
-
- _bfd_vms_output_flush (abfd);
-
- }
-
- _bfd_vms_output_alignment (abfd, 8);
- _bfd_vms_output_pop (abfd);
- _bfd_vms_output_end (abfd);
-
- return 0;
-}
+++ /dev/null
-/* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
- EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
- 2007, 2008, 2009 Free Software Foundation, Inc.
-
- HDR record handling functions
- EMH record handling functions
-
- EOM record handling functions
- EEOM record handling functions
-
- IHD record handling functions
- EIHD record handling functions
-
- ISD record handling functions
- EISD record handling functions
-
- IHS record handling functions
- EIHS record handling functions
-
- DBG record handling functions
- EDBG record handling functions
-
- TBT record handling functions
- ETBT record handling functions
-
- DST/DMT section handling functions
-
- Written by Klaus K"ampf (kkaempf@rmi.de)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
-
-#include "sysdep.h"
-#include "bfd.h"
-#include "bfdver.h"
-#include "bfdlink.h"
-#include "safe-ctype.h"
-#include "libbfd.h"
-
-#include "vms.h"
-
-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. */
-
-int
-_bfd_vms_slurp_hdr (bfd *abfd, int objtype)
-{
- unsigned char *ptr;
- unsigned char *vms_rec;
- int subtype;
-
- vms_rec = PRIV(vms_rec);
-
-#if VMS_DEBUG
- vms_debug(2, "HDR/EMH\n");
-#endif
-
- switch (objtype)
- {
- case OBJ_S_C_HDR:
- subtype = vms_rec[1];
- break;
- case EOBJ_S_C_EMH:
- subtype = bfd_getl16 (vms_rec + 4) + EVAX_OFFSET;
- break;
- default:
- subtype = -1;
- }
-
-#if VMS_DEBUG
- vms_debug(3, "subtype %d\n", subtype);
-#endif
-
- switch (subtype)
- {
- case MHD_S_C_MHD:
- /* Module header. */
- PRIV (hdr_data).hdr_b_strlvl = vms_rec[2];
- PRIV (hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3);
- PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5);
- ptr = vms_rec + 5 + vms_rec[5] + 1;
- PRIV (hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr);
- ptr += *ptr + 1;
- PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
- break;
-
- case MHD_S_C_LNM:
- PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
- break;
-
- case MHD_S_C_SRC:
- PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
- break;
-
- case MHD_S_C_TTL:
- PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
- break;
-
- case EMH_S_C_MHD + EVAX_OFFSET:
- /* Module header. */
- PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
- PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
- PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
- PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
- PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20);
- ptr = vms_rec + 20 + vms_rec[20] + 1;
- PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
- ptr += *ptr + 1;
- PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
- break;
-
- case EMH_S_C_LNM + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
- break;
-
- case EMH_S_C_SRC + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
- break;
-
- case EMH_S_C_TTL + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
- break;
-
- case MHD_S_C_CPR:
- case MHD_S_C_MTC:
- case MHD_S_C_GTX:
- case EMH_S_C_CPR + EVAX_OFFSET:
- case EMH_S_C_MTC + EVAX_OFFSET:
- case EMH_S_C_GTX + EVAX_OFFSET:
- break;
-
- default:
- bfd_set_error (bfd_error_wrong_format);
- return -1;
- }
-
- return 0;
-}
-
-/* Output routines. */
-
-/* Manufacture a VMS like time on a unix based system.
- stolen from obj-vms.c. */
-
-static unsigned char *
-get_vms_time_string (void)
-{
- static unsigned char tbuf[18];
-#ifndef VMS
-#include <time.h>
-
- char *pnt;
- time_t timeb;
-
- time (& timeb);
- pnt = ctime (&timeb);
- pnt[3] = 0;
- pnt[7] = 0;
- pnt[10] = 0;
- pnt[16] = 0;
- pnt[24] = 0;
- sprintf ((char *) tbuf, "%2s-%3s-%s %s",
- pnt + 8, pnt + 4, pnt + 20, pnt + 11);
-#else
-#include <starlet.h>
- struct
- {
- int Size;
- unsigned char *Ptr;
- } Descriptor;
- Descriptor.Size = 17;
- Descriptor.Ptr = tbuf;
- SYS$ASCTIM (0, &Descriptor, 0, 0);
-#endif /* not VMS */
-
-#if VMS_DEBUG
- vms_debug (6, "vmstimestring:'%s'\n", tbuf);
-#endif
-
- return tbuf;
-}
-
-/* Write object header for bfd abfd. */
-
-int
-_bfd_vms_write_hdr (bfd *abfd, int objtype)
-{
- asymbol *symbol;
- 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);
-#endif
-
- _bfd_vms_output_alignment (abfd, 2);
-
- /* MHD. */
- if (objtype != OBJ_S_C_HDR)
- {
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD);
- _bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL);
- _bfd_vms_output_long (abfd, 0);
- _bfd_vms_output_long (abfd, 0);
- _bfd_vms_output_long (abfd, MAX_OUTREC_SIZE);
- }
-
- /* Create module name from filename. */
- if (bfd_get_filename (abfd) != 0)
- {
- char *module = vms_get_module_name (bfd_get_filename (abfd), TRUE);
- _bfd_vms_output_counted (abfd, module);
- free (module);
- }
- else
- _bfd_vms_output_counted (abfd, "NONAME");
-
- _bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
- _bfd_vms_output_dump (abfd, get_vms_time_string (), EMH_DATE_LENGTH);
- _bfd_vms_output_fill (abfd, 0, EMH_DATE_LENGTH);
- _bfd_vms_output_flush (abfd);
-
- /* LMN. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM);
- snprintf (version, sizeof (version), "GAS BFD v%s", BFD_VERSION_STRING);
- _bfd_vms_output_dump (abfd, (unsigned char *)version, strlen (version));
- _bfd_vms_output_flush (abfd);
-
- /* SRC. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC);
-
- for (symnum = 0; symnum < abfd->symcount; symnum++)
- {
- symbol = abfd->outsymbols[symnum];
-
- if (symbol->flags & BSF_FILE)
- {
- if (CONST_STRNEQ ((char *)symbol->name, "<CASE:"))
- {
- PRIV (flag_hash_long_names) = symbol->name[6] - '0';
- PRIV (flag_show_after_trunc) = symbol->name[7] - '0';
-
- if (had_file)
- break;
- had_case = 1;
- continue;
- }
-
- _bfd_vms_output_dump (abfd, (unsigned char *) symbol->name,
- (int) strlen (symbol->name));
- if (had_case)
- break;
- had_file = 1;
- }
- }
-
- if (symnum == abfd->symcount)
- _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("noname"));
-
- _bfd_vms_output_flush (abfd);
-
- /* TTL. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL);
- _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("TTL"));
- _bfd_vms_output_flush (abfd);
-
- /* CPR. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR);
- _bfd_vms_output_dump (abfd,
- (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996",
- 39);
- _bfd_vms_output_flush (abfd);
-
- return 0;
-}
-
-/* Process EOM/EEOM record
- return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_eom (bfd *abfd, int objtype)
-{
- unsigned char *vms_rec;
-
-#if VMS_DEBUG
- vms_debug(2, "EOM/EEOM\n");
-#endif
-
- vms_rec = PRIV (vms_rec);
-
- if ((objtype == OBJ_S_C_EOM)
- || (objtype == OBJ_S_C_EOMW))
- {
- }
- else
- {
- PRIV (eom_data).eom_l_total_lps
- = bfd_getl32 (vms_rec + EEOM_S_L_TOTAL_LPS);
- PRIV (eom_data).eom_w_comcod = bfd_getl16 (vms_rec + EEOM_S_W_COMCOD);
- if (PRIV (eom_data).eom_w_comcod > 1)
- {
- (*_bfd_error_handler) (_("Object module NOT error-free !\n"));
- bfd_set_error (bfd_error_bad_value);
- return -1;
- }
- PRIV (eom_data).eom_has_transfer = FALSE;
- if (PRIV (rec_size) > 10)
- {
- PRIV (eom_data).eom_has_transfer = TRUE;
- PRIV (eom_data).eom_b_tfrflg = vms_rec[EEOM_S_B_TFRFLG];
- PRIV (eom_data).eom_l_psindx
- = bfd_getl32 (vms_rec + EEOM_S_L_PSINDX);
- PRIV (eom_data).eom_l_tfradr
- = bfd_getl32 (vms_rec + EEOM_S_L_TFRADR);
-
- abfd->start_address = PRIV (eom_data).eom_l_tfradr;
- }
- }
- return 0;
-}
-
-/* Write eom record for bfd abfd. */
-
-int
-_bfd_vms_write_eom (bfd *abfd, int objtype)
-{
-#if VMS_DEBUG
- vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype);
-#endif
-
- _bfd_vms_output_begin (abfd, objtype, -1);
- _bfd_vms_output_long (abfd, (unsigned long) (PRIV (vms_linkage_index) >> 1));
- _bfd_vms_output_byte (abfd, 0); /* Completion code. */
- _bfd_vms_output_byte (abfd, 0); /* Fill byte. */
-
- if (bfd_get_start_address (abfd) != (bfd_vma)-1)
- {
- asection *section;
-
- section = bfd_get_section_by_name (abfd, ".link");
- if (section == 0)
- {
- bfd_set_error (bfd_error_nonrepresentable_section);
- return -1;
- }
- _bfd_vms_output_short (abfd, 0);
- _bfd_vms_output_long (abfd, (unsigned long) (section->index));
- _bfd_vms_output_long (abfd,
- (unsigned long) bfd_get_start_address (abfd));
- _bfd_vms_output_long (abfd, 0);
- }
-
- _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 msize = 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, msize, 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 = msize;
- 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, %d)\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;
-}
#include "libbfd.h"
#include "safe-ctype.h"
-#include "vms.h"
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#ifdef VMS
+#include <rms.h>
+#include <unixlib.h>
+#include <starlet.h>
+#define RME$C_SETRFM 0x00000001
+#include <unistd.h>
+#endif
+#include <time.h>
-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 ));
+#include "vms.h"
+#include "vms/emh.h"
#if VMS_DEBUG
/* Debug functions. */
if (abslvl > min_level)
return;
- while (--level>0)
+ while (--level > 0)
fprintf (output, " ");
va_start (args, format);
vfprintf (output, format, args);
hex dump 'size' bytes starting at 'ptr'. */
void
-_bfd_hexdump (int level,
- unsigned char *ptr,
- int size,
- int offset)
+_bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
{
unsigned char *lptr = ptr;
int count = 0;
while (size-- > 0)
{
- if ((count%16) == 0)
+ if ((count % 16) == 0)
vms_debug (level, "%08lx:", start);
vms_debug (-level, " %02x", *ptr++);
count++;
start++;
if (size == 0)
{
- while ((count%16) != 0)
+ while ((count % 16) != 0)
{
vms_debug (-level, " ");
count++;
}
}
- if ((count%16) == 0)
+ if ((count % 16) == 0)
{
vms_debug (-level, " ");
while (lptr < ptr)
{
- vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
+ vms_debug (-level, "%c", (*lptr < 32) ? '.' : *lptr);
lptr++;
}
vms_debug (-level, "\n");
}
}
- if ((count%16) != 0)
+ if ((count % 16) != 0)
vms_debug (-level, "\n");
}
#endif
\f
-/* Hash functions
-
- These are needed when reading an object file. */
-
-/* Allocate new vms_hash_entry
- keep the symbol name and a pointer to the bfd symbol in the table. */
-
-struct bfd_hash_entry *
-_bfd_vms_hash_newfunc (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string)
-{
- vms_symbol_entry *ret;
-
-#if VMS_DEBUG
- vms_debug (5, "_bfd_vms_hash_newfunc (%p, %p, %s)\n", entry, table, string);
-#endif
-
- if (entry == NULL)
- {
- ret = (vms_symbol_entry *)
- bfd_hash_allocate (table, sizeof (vms_symbol_entry));
- if (ret == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
- entry = (struct bfd_hash_entry *) ret;
- }
-
- /* Call the allocation method of the base class. */
- ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
-#endif
-
- ret->symbol = NULL;
-
- return (struct bfd_hash_entry *)ret;
-}
-\f
-/* Object file input functions. */
-
-/* Return type and size from record header (buf) on Alpha. */
-
-void
-_bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
- unsigned char *buf,
- int *type,
- int *size)
-{
- if (type)
- *type = bfd_getl16 (buf);
-
- if (size)
- *size = bfd_getl16 (buf+2);
-
-#if VMS_DEBUG
- vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
- type ? *type : 0, size ? *size : 0);
-#endif
-}
-
-/* Get next record from object file to vms_buf.
- Set PRIV(buf_size) and return it
-
- This is a little tricky since it should be portable.
-
- The openVMS object file has 'variable length' which means that
- read() returns data in chunks of (hopefully) correct and expected
- size. The linker (and other tools on VMS) depend on that. Unix
- doesn't know about 'formatted' files, so reading and writing such
- an object file in a Unix environment is not trivial.
-
- With the tool 'file' (available on all VMS FTP sites), one
- can view and change the attributes of a file. Changing from
- 'variable length' to 'fixed length, 512 bytes' reveals the
- record size at the first 2 bytes of every record. The same
- may happen during the transfer of object files from VMS to Unix,
- at least with UCX, the DEC implementation of TCP/IP.
-
- The VMS format repeats the size at bytes 2 & 3 of every record.
-
- On the first call (file_format == FF_UNKNOWN) we check if
- the first and the third byte pair (!) of the record match.
- If they do it's an object file in an Unix environment or with
- wrong attributes (FF_FOREIGN), else we should be in a VMS
- environment where read() returns the record size (FF_NATIVE).
-
- Reading is always done in 2 steps:
- 1. first just the record header is read and the size extracted,
- 2. then the read buffer is adjusted and the remaining bytes are
- read in.
-
- All file I/O is done on even file positions. */
-
-#define VMS_OBJECT_ADJUSTMENT 2
-
-static void
-maybe_adjust_record_pointer_for_object (bfd *abfd)
-{
- /* Set the file format once for all on the first invocation. */
- if (PRIV (file_format) == FF_UNKNOWN)
- {
- if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4]
- && PRIV (vms_rec)[1] == PRIV (vms_rec)[5])
- PRIV (file_format) = FF_FOREIGN;
- else
- PRIV (file_format) = FF_NATIVE;
- }
-
- /* The adjustment is needed only in an Unix environment. */
- if (PRIV (file_format) == FF_FOREIGN)
- PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT;
-}
-
-/* Get first record from file and return the file type. */
-
-int
-_bfd_vms_get_first_record (bfd *abfd)
-{
- unsigned int test_len;
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_get_first_record\n");
-#endif
-
- if (PRIV (is_vax))
- test_len = 0;
- else
- /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
- 2 bytes size repeated) and 12 bytes for images (4 bytes major id,
- 4 bytes minor id, 4 bytes length). */
- test_len = 12;
-
- /* Size the main buffer. */
- if (PRIV (buf_size) == 0)
- {
- /* On VAX there's no size information in the record, so
- start with OBJ_S_C_MAXRECSIZ. */
- bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ);
- PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
- PRIV (buf_size) = amt;
- }
-
- /* Initialize the record pointer. */
- PRIV (vms_rec) = PRIV (vms_buf);
-
- /* We only support modules on VAX. */
- if (PRIV (is_vax))
- {
- if (vms_get_remaining_object_record (abfd, test_len) <= 0)
- return FT_UNKNOWN;
-
-#if VMS_DEBUG
- vms_debug (2, "file type is VAX module\n");
-#endif
-
- return FT_MODULE;
- }
-
- if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
- {
- bfd_set_error (bfd_error_file_truncated);
- return FT_UNKNOWN;
- }
-
- /* Is it an image? */
- if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID)
- && (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID))
- {
- if (vms_get_remaining_image_record (abfd, test_len) <= 0)
- return FT_UNKNOWN;
-
-#if VMS_DEBUG
- vms_debug (2, "file type is image\n");
-#endif
-
- return FT_IMAGE;
- }
-
- /* Assume it's a module and adjust record pointer if necessary. */
- maybe_adjust_record_pointer_for_object (abfd);
-
- /* But is it really a module? */
- if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP
- && bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ)
- {
- if (vms_get_remaining_object_record (abfd, test_len) <= 0)
- return FT_UNKNOWN;
-
-#if VMS_DEBUG
- vms_debug (2, "file type is module\n");
-#endif
-
- return FT_MODULE;
- }
-
-#if VMS_DEBUG
- vms_debug (2, "file type is unknown\n");
-#endif
-
- return FT_UNKNOWN;
-}
-
-/* Implement step #1 of the object record reading procedure.
- Return the record type or -1 on failure. */
-
-int
-_bfd_vms_get_object_record (bfd *abfd)
-{
- unsigned int test_len;
- int type;
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_get_obj_record\n");
-#endif
-
- if (PRIV (is_vax))
- test_len = 0;
- else
- {
- int off = 0;
-
- /* See _bfd_vms_get_first_record. */
- test_len = 6;
-
- /* Skip odd alignment byte. */
- if (bfd_tell (abfd) & 1)
- {
- if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
- {
- bfd_set_error (bfd_error_file_truncated);
- return -1;
- }
- /* Alignment byte may be present or not. This is not easy to
- detect but all object record types are not 0 (on Alpha VMS).
- We also hope that pad byte is 0. */
- if (PRIV (vms_buf)[0])
- off = 1;
- }
-
- /* Read the record header */
- if (bfd_bread (PRIV (vms_buf) + off, test_len - off, abfd)
- != test_len - off)
- {
- bfd_set_error (bfd_error_file_truncated);
- return -1;
- }
-
- /* Reset the record pointer. */
- PRIV (vms_rec) = PRIV (vms_buf);
- maybe_adjust_record_pointer_for_object (abfd);
- }
-
- if (vms_get_remaining_object_record (abfd, test_len) <= 0)
- return -1;
-
- if (PRIV (is_vax))
- type = PRIV (vms_rec) [0];
- else
- type = bfd_getl16 (PRIV (vms_rec));
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
- PRIV (vms_rec), PRIV (rec_size), type);
-#endif
-
- return type;
-}
-
-/* Implement step #2 of the object record reading procedure.
- Return the size of the record or 0 on failure. */
-
-static int
-vms_get_remaining_object_record (bfd *abfd, int read_so_far)
-{
-#if VMS_DEBUG
- vms_debug (8, "vms_get_remaining_obj_record\n");
-#endif
-
- if (PRIV (is_vax))
- {
- if (read_so_far != 0)
- abort ();
-
- PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd);
-
- if (PRIV (rec_size) <= 0)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* Reset the record pointer. */
- PRIV (vms_rec) = PRIV (vms_buf);
- }
- else
- {
- unsigned int to_read;
-
- /* Extract record size. */
- PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
-
- if (PRIV (rec_size) <= 0)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* That's what the linker manual says. */
- if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* Take into account object adjustment. */
- to_read = PRIV (rec_size);
- if (PRIV (file_format) == FF_FOREIGN)
- to_read += VMS_OBJECT_ADJUSTMENT;
-
- /* Adjust the buffer. */
- if (to_read > PRIV (buf_size))
- {
- PRIV (vms_buf)
- = (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read);
- if (PRIV (vms_buf) == NULL)
- return 0;
- PRIV (buf_size) = to_read;
- }
-
- /* Read the remaining record. */
- to_read -= read_so_far;
-
-#if VMS_DEBUG
- vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
-#endif
-
- if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* Reset the record pointer. */
- PRIV (vms_rec) = PRIV (vms_buf);
- maybe_adjust_record_pointer_for_object (abfd);
- }
-
-#if VMS_DEBUG
- vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
-#endif
-
- return PRIV (rec_size);
-}
-
-/* Implement step #2 of the record reading procedure for images.
- Return the size of the record or 0 on failure. */
-
-static int
-vms_get_remaining_image_record (bfd *abfd, int read_so_far)
-{
- unsigned int to_read;
- int remaining;
-
- /* Extract record size. */
- PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
-
- if (PRIV (rec_size) > PRIV (buf_size))
- {
- PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size));
-
- if (PRIV (vms_buf) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return 0;
- }
-
- PRIV (buf_size) = PRIV (rec_size);
- }
-
- /* Read the remaining record. */
- remaining = PRIV (rec_size) - read_so_far;
- to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
-
- while (remaining > 0)
- {
- if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- read_so_far += to_read;
- remaining -= to_read;
-
- /* Eat trailing 0xff's. */
- if (remaining > 0)
- while (PRIV (vms_buf) [read_so_far - 1] == 0xff)
- read_so_far--;
-
- to_read = MIN (VMS_BLOCK_SIZE, remaining);
- }
-
- /* Reset the record pointer. */
- PRIV (vms_rec) = PRIV (vms_buf);
-
- return PRIV (rec_size);
-}
/* Copy sized string (string with fixed size) to new allocated area
size is string size (size of record) */
if (newstr == NULL)
return NULL;
- strncpy (newstr, (char *) str, (size_t) size);
+ memcpy (newstr, (char *) str, (size_t) size);
newstr[size] = 0;
return newstr;
return _bfd_vms_save_sized_string (ptr, len);
}
\f
-/* Stack routines for vms ETIR commands. */
+/* Object output routines. */
-/* Push value and section index. */
+/* Begin new record.
+ Write 2 bytes rectype and 2 bytes record length. */
void
-_bfd_vms_push (bfd * abfd, uquad val, int psect)
+_bfd_vms_output_begin (struct vms_rec_wr *recwr, int rectype)
{
- static int last_psect;
+ vms_debug2 ((6, "_bfd_vms_output_begin (type %d)\n", rectype));
-#if VMS_DEBUG
- vms_debug (4, "<push %016lx (%d) at %d>\n", val, psect, PRIV (stackptr));
-#endif
-
- if (psect >= 0)
- last_psect = psect;
+ /* Record must have been closed. */
+ BFD_ASSERT (recwr->size == 0);
- PRIV (stack[PRIV (stackptr)]).value = val;
- PRIV (stack[PRIV (stackptr)]).psect = last_psect;
- PRIV (stackptr)++;
- if (PRIV (stackptr) >= STACKSIZE)
- {
- bfd_set_error (bfd_error_bad_value);
- (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
- exit (1);
- }
-}
+ _bfd_vms_output_short (recwr, (unsigned int) rectype);
-/* Pop value and section index. */
-
-uquad
-_bfd_vms_pop (bfd * abfd, int *psect)
-{
- uquad value;
-
- if (PRIV (stackptr) == 0)
- {
- bfd_set_error (bfd_error_bad_value);
- (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
- exit (1);
- }
- PRIV (stackptr)--;
- value = PRIV (stack[PRIV (stackptr)]).value;
- if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
- *psect = PRIV (stack[PRIV (stackptr)]).psect;
-
-#if VMS_DEBUG
- vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
-#endif
-
- return value;
+ /* Placeholder for length. */
+ _bfd_vms_output_short (recwr, 0);
}
-\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). */
+/* Begin new sub-record.
+ Write 2 bytes rectype, and 2 bytes record length. */
void
-_bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
+_bfd_vms_output_begin_subrec (struct vms_rec_wr *recwr, int rectype)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_begin (type %d, head %d)\n", rectype,
- rechead);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_begin_subrec (type %d)\n", rectype));
- _bfd_vms_output_short (abfd, (unsigned int) rectype);
+ /* Subrecord must have been closed. */
+ BFD_ASSERT (recwr->subrec_offset == 0);
- /* Save current output position to fill in length later. */
+ /* Save start of subrecord offset. */
+ recwr->subrec_offset = recwr->size;
- if (PRIV (push_level) > 0)
- PRIV (length_pos) = PRIV (output_size);
-
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
- PRIV (length_pos));
-#endif
+ /* Subrecord type. */
+ _bfd_vms_output_short (recwr, (unsigned int) rectype);
/* Placeholder for length. */
- _bfd_vms_output_short (abfd, 0);
-
- if (rechead != -1)
- _bfd_vms_output_short (abfd, (unsigned int) rechead);
+ _bfd_vms_output_short (recwr, 0);
}
/* Set record/subrecord alignment. */
void
-_bfd_vms_output_alignment (bfd * abfd, int alignto)
+_bfd_vms_output_alignment (struct vms_rec_wr *recwr, int alignto)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_alignment (%d)\n", alignto);
-#endif
-
- PRIV (output_alignment) = alignto;
+ vms_debug2 ((6, "_bfd_vms_output_alignment (%d)\n", alignto));
+ recwr->align = alignto;
}
-/* Prepare for subrecord fields. */
-
-void
-_bfd_vms_output_push (bfd * abfd)
-{
-#if VMS_DEBUG
- vms_debug (6, "vms_output_push (pushed_size = %d)\n", PRIV (output_size));
-#endif
+/* Align the size of the current record (whose length is LENGTH).
+ Warning: this obviously changes the record (and the possible subrecord)
+ length. */
- PRIV (push_level)++;
- PRIV (pushed_size) = PRIV (output_size);
-}
-
-/* End of subrecord fields. */
-
-void
-_bfd_vms_output_pop (bfd * abfd)
+static void
+_bfd_vms_output_align (struct vms_rec_wr *recwr, unsigned int length)
{
-#if VMS_DEBUG
- vms_debug (6, "vms_output_pop (pushed_size = %d)\n", PRIV (pushed_size));
-#endif
-
- _bfd_vms_output_flush (abfd);
- PRIV (length_pos) = 2;
+ unsigned int real_size = recwr->size;
+ unsigned int aligncount;
-#if VMS_DEBUG
- vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
-#endif
+ /* Pad with 0 if alignment is required. */
+ aligncount = (recwr->align - (length % recwr->align)) % recwr->align;
+ vms_debug2 ((6, "align: adding %d bytes\n", aligncount));
+ while (aligncount-- > 0)
+ recwr->buf[real_size++] = 0;
- PRIV (pushed_size) = 0;
- PRIV (push_level)--;
+ recwr->size = real_size;
}
-/* Flush unwritten output, ends current record. */
+/* Ends current sub-record. Set length field. */
void
-_bfd_vms_output_flush (bfd * abfd)
+_bfd_vms_output_end_subrec (struct vms_rec_wr *recwr)
{
- int real_size = PRIV (output_size);
- int aligncount;
+ int real_size = recwr->size;
int length;
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_flush (real_size = %d, pushed_size %d at lenpos %d)\n",
- real_size, PRIV (pushed_size), PRIV (length_pos));
-#endif
+ /* Subrecord must be open. */
+ BFD_ASSERT (recwr->subrec_offset != 0);
- if (PRIV (push_level) > 0)
- length = real_size - PRIV (pushed_size);
- else
- length = real_size;
+ length = real_size - recwr->subrec_offset;
if (length == 0)
return;
- aligncount = (PRIV (output_alignment)
- - (length % PRIV (output_alignment))) % PRIV (output_alignment);
-
-#if VMS_DEBUG
- vms_debug (6, "align: adding %d bytes\n", aligncount);
-#endif
- while (aligncount-- > 0)
- {
- PRIV (output_buf)[real_size++] = 0;
- length++;
- }
+ _bfd_vms_output_align (recwr, length);
/* Put length to buffer. */
- PRIV (output_size) = PRIV (length_pos);
- _bfd_vms_output_short (abfd, (unsigned int) length);
+ bfd_putl16 ((bfd_vma) (recwr->size - recwr->subrec_offset),
+ recwr->buf + recwr->subrec_offset + 2);
- if (PRIV (push_level) == 0)
- {
- /* File is open in undefined (UDF) format on VMS, but ultimately will be
- converted to variable length (VAR) format. VAR format has a length
- word first which must be explicitly output in UDF format. */
- bfd_bwrite (PRIV (output_buf) + 2, 2, abfd);
- bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd);
- PRIV (output_size) = 0;
- }
- else
- {
- PRIV (output_size) = real_size;
- PRIV (pushed_size) = PRIV (output_size);
- }
+ /* Close the subrecord. */
+ recwr->subrec_offset = 0;
}
-/* End record output. */
+/* Ends current record (and write it). */
void
-_bfd_vms_output_end (bfd * abfd)
+_bfd_vms_output_end (bfd *abfd, struct vms_rec_wr *recwr)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_end\n");
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_end (size %u)\n", recwr->size));
- _bfd_vms_output_flush (abfd);
-}
+ /* Subrecord must have been closed. */
+ BFD_ASSERT (recwr->subrec_offset == 0);
+
+ if (recwr->size == 0)
+ return;
-/* Check remaining buffer size
+ _bfd_vms_output_align (recwr, recwr->size);
- Return what's left. */
+ /* Write the length word. */
+ bfd_putl16 ((bfd_vma) recwr->size, recwr->buf + 2);
+
+ /* 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. */
+ /* So, first the length word. */
+ bfd_bwrite (recwr->buf + 2, 2, abfd);
+
+ /* Align. */
+ if (recwr->size & 1)
+ recwr->buf[recwr->size++] = 0;
+
+ /* Then the record. */
+ bfd_bwrite (recwr->buf, (size_t) recwr->size, abfd);
+
+ recwr->size = 0;
+}
+
+/* Check remaining buffer size. Return what's left. */
int
-_bfd_vms_output_check (bfd * abfd, int size)
+_bfd_vms_output_check (struct vms_rec_wr *recwr, int size)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_check (%d)\n", size);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_check (%d)\n", size));
- return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
+ return (MAX_OUTREC_SIZE - (recwr->size + size + MIN_OUTREC_LUFT));
}
/* Output byte (8 bit) value. */
void
-_bfd_vms_output_byte (bfd * abfd, unsigned int value)
+_bfd_vms_output_byte (struct vms_rec_wr *recwr, unsigned int value)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_byte (%02x)\n", value));
- bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
- PRIV (output_size) += 1;
+ *(recwr->buf + recwr->size) = value;
+ recwr->size += 1;
}
/* Output short (16 bit) value. */
void
-_bfd_vms_output_short (bfd * abfd, unsigned int value)
+_bfd_vms_output_short (struct vms_rec_wr *recwr, unsigned int value)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_short (%04x)\n", value));
- bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
- PRIV (output_buf) + PRIV (output_size));
- PRIV (output_size) += 2;
+ bfd_putl16 ((bfd_vma) value & 0xffff, recwr->buf + recwr->size);
+ recwr->size += 2;
}
/* Output long (32 bit) value. */
void
-_bfd_vms_output_long (bfd * abfd, unsigned long value)
+_bfd_vms_output_long (struct vms_rec_wr *recwr, unsigned long value)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_long (%08lx)\n", value));
- bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
- PRIV (output_size) += 4;
+ bfd_putl32 ((bfd_vma) value, recwr->buf + recwr->size);
+ recwr->size += 4;
}
/* Output quad (64 bit) value. */
void
-_bfd_vms_output_quad (bfd * abfd, uquad value)
+_bfd_vms_output_quad (struct vms_rec_wr *recwr, bfd_vma value)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_quad (%08lx)\n", (unsigned long)value));
- bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
- PRIV (output_size) += 8;
+ bfd_putl64 (value, recwr->buf + recwr->size);
+ recwr->size += 8;
}
/* Output c-string as counted string. */
void
-_bfd_vms_output_counted (bfd * abfd, char *value)
+_bfd_vms_output_counted (struct vms_rec_wr *recwr, char *value)
{
int len;
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_counted (%s)\n", value);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_counted (%s)\n", value));
len = strlen (value);
if (len == 0)
(*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
return;
}
- _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
- _bfd_vms_output_dump (abfd, (unsigned char *) value, len);
+ _bfd_vms_output_byte (recwr, (unsigned int) len & 0xff);
+ _bfd_vms_output_dump (recwr, (unsigned char *) value, len);
}
/* Output character area. */
void
-_bfd_vms_output_dump (bfd * abfd,
- unsigned char *data,
- int length)
+_bfd_vms_output_dump (struct vms_rec_wr *recwr, unsigned char *data, int len)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_dump (%d)\n", length);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_dump (%d)\n", len));
- if (length == 0)
+ if (len == 0)
return;
- memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
- PRIV (output_size) += length;
+ memcpy (recwr->buf + recwr->size, data, (size_t) len);
+ recwr->size += len;
}
/* Output count bytes of value. */
void
-_bfd_vms_output_fill (bfd * abfd,
- int value,
- int count)
+_bfd_vms_output_fill (struct vms_rec_wr *recwr, int value, int count)
{
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count);
-#endif
+ vms_debug2 ((6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count));
if (count == 0)
return;
- memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
- PRIV (output_size) += count;
-}
-
-/* This hash routine borrowed from GNU-EMACS, and strengthened slightly. ERY. */
-
-static int
-hash_string (const char *ptr)
-{
- const unsigned char *p = (unsigned char *) ptr;
- const unsigned char *end = p + strlen (ptr);
- unsigned char c;
- int hash = 0;
-
- while (p != end)
- {
- c = *p++;
- hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
- }
- return hash;
+ memset (recwr->buf + recwr->size, value, (size_t) count);
+ recwr->size += count;
}
-/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
+#ifdef VMS
+/* Convert the file to variable record length format. This is done
+ using undocumented system call sys$modify().
+ Pure VMS version. */
-char *
-_bfd_vms_length_hash_symbol (bfd * abfd, const char *in, int maxlen)
+static void
+vms_convert_to_var (char *vms_filename)
{
- unsigned long result;
- int in_len;
- char *new_name;
- const char *old_name;
- int i;
- static char outbuf[EOBJ_S_C_SYMSIZ+1];
- char *out = outbuf;
-
-#if VMS_DEBUG
- vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
-#endif
-
- if (maxlen > EOBJ_S_C_SYMSIZ)
- maxlen = EOBJ_S_C_SYMSIZ;
-
- /* Save this for later. */
- new_name = out;
-
- /* We may need to truncate the symbol, save the hash for later. */
- in_len = strlen (in);
+ struct FAB fab = cc$rms_fab;
- result = (in_len > maxlen) ? hash_string (in) : 0;
+ 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;
- old_name = in;
+ sys$open (&fab);
- /* Do the length checking. */
- if (in_len <= maxlen)
- i = in_len;
- else
- {
- if (PRIV (flag_hash_long_names))
- i = maxlen-9;
- else
- i = maxlen;
- }
-
- strncpy (out, in, (size_t) i);
- in += i;
- out += i;
-
- if ((in_len > maxlen)
- && PRIV (flag_hash_long_names))
- sprintf (out, "_%08lx", result);
- else
- *out = 0;
-
-#if VMS_DEBUG
- vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
-#endif
-
- if (in_len > maxlen
- && PRIV (flag_hash_long_names)
- && PRIV (flag_show_after_trunc))
- printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
+ fab.fab$b_rfm = FAB$C_VAR;
- return outbuf;
+ sys$modify (&fab);
+ sys$close (&fab);
}
-/* Allocate and initialize a new symbol. */
-
-static asymbol *
-new_symbol (bfd * abfd, char *name)
+static int
+vms_convert_to_var_1 (char *filename, int type)
{
- asymbol *symbol;
-
-#if VMS_DEBUG
- _bfd_vms_debug (7, "new_symbol %s\n", name);
-#endif
-
- symbol = bfd_make_empty_symbol (abfd);
- if (symbol == 0)
- return symbol;
- symbol->name = name;
- symbol->section = (asection *)(unsigned long)-1;
-
- return symbol;
+ if (type != DECC$K_FILE)
+ return FALSE;
+ vms_convert_to_var (filename);
+ return TRUE;
}
-/* Allocate and enter a new private symbol. */
+/* Convert the file to variable record length format. This is done
+ using undocumented system call sys$modify().
+ Unix filename version. */
-vms_symbol_entry *
-_bfd_vms_enter_symbol (bfd * abfd, char *name)
-{
- vms_symbol_entry *entry;
-
-#if VMS_DEBUG
- _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
-#endif
-
- entry = (vms_symbol_entry *)
- bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
- if (entry == 0)
- {
-#if VMS_DEBUG
- _bfd_vms_debug (8, "creating hash entry for %s\n", name);
-#endif
- entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
- name, TRUE, FALSE);
- if (entry != 0)
- {
- asymbol *symbol;
- symbol = new_symbol (abfd, name);
- if (symbol != 0)
- {
- entry->symbol = symbol;
- PRIV (gsd_sym_count)++;
- abfd->symcount++;
- }
- else
- entry = 0;
- }
- else
- (*_bfd_error_handler) (_("failed to enter %s"), name);
- }
- else
- {
-#if VMS_DEBUG
- _bfd_vms_debug (8, "found hash entry for %s\n", name);
-#endif
- }
-
-#if VMS_DEBUG
- _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
-#endif
- return entry;
+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 */
+
+/* Manufacture a VMS like time on a unix based system.
+ stolen from obj-vms.c. */
+
+unsigned char *
+get_vms_time_string (void)
+{
+ static unsigned char tbuf[18];
+#ifndef VMS
+ char *pnt;
+ time_t timeb;
+
+ time (& timeb);
+ pnt = ctime (&timeb);
+ pnt[3] = 0;
+ pnt[7] = 0;
+ pnt[10] = 0;
+ pnt[16] = 0;
+ pnt[24] = 0;
+ sprintf ((char *) tbuf, "%2s-%3s-%s %s",
+ pnt + 8, pnt + 4, pnt + 20, pnt + 11);
+#else
+ struct
+ {
+ int Size;
+ unsigned char *Ptr;
+ } Descriptor;
+ Descriptor.Size = 17;
+ Descriptor.Ptr = tbuf;
+ SYS$ASCTIM (0, &Descriptor, 0, 0);
+#endif /* not VMS */
+
+ vms_debug2 ((6, "vmstimestring:'%s'\n", tbuf));
+
+ return tbuf;
}
/* Create module name from filename (ie, extract the basename and convert it
+++ /dev/null
-/* vms-tir.c -- BFD back-end for VAX (openVMS/VAX) and
- EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007,
- 2008, 2009 Free Software Foundation, Inc.
-
- TIR record handling functions
- ETIR record handling functions
-
- Go and read the openVMS linker manual (esp. appendix B)
- if you don't know what's going on here :-)
-
- Written by Klaus K"ampf (kkaempf@rmi.de)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- 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)
- by byte (1 byte)
- sh short (2 byte, 16 bit)
- lw longword (4 byte, 32 bit)
- qw quadword (8 byte, 64 bit)
- da data stream */
-
-#include "sysdep.h"
-#include "bfd.h"
-#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)
-{
- bfd_size_type offset;
-
- offset = PRIV (image_ptr) - PRIV (image_section)->contents;
- if (offset + size > PRIV (image_section)->size)
- {
- PRIV (image_section)->contents
- = bfd_realloc_or_free (PRIV (image_section)->contents, offset + size);
- if (PRIV (image_section)->contents == NULL)
- {
- (*_bfd_error_handler) (_("No Mem !"));
- return -1;
- }
- PRIV (image_section)->size = offset + size;
- PRIV (image_ptr) = PRIV (image_section)->contents + offset;
- }
-
- return 0;
-}
-
-/* Routines to fill sections contents during tir/etir read. */
-
-/* Initialize image buffer pointer to be filled. */
-
-static void
-image_set_ptr (bfd * abfd, int psect, uquad offset)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (4, "image_set_ptr (%d=%s, %d)\n",
- psect, PRIV (sections)[psect]->name, offset);
-#endif
-
- PRIV (image_ptr) = PRIV (sections)[psect]->contents + offset;
- PRIV (image_section) = PRIV (sections)[psect];
-}
-
-/* Increment image buffer pointer by offset. */
-
-static void
-image_inc_ptr (bfd * abfd, uquad offset)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (4, "image_inc_ptr (%d)\n", offset);
-#endif
-
- 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
-image_dump (bfd * abfd,
- unsigned char *ptr,
- int size,
- int offset ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (8, "image_dump from (%p, %d) to (%p)\n", ptr, size,
- PRIV (image_ptr));
- _bfd_hexdump (9, ptr, size, offset);
-#endif
-
- 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++;
-}
-
-/* Write byte to section image. */
-
-static void
-image_write_b (bfd * abfd, unsigned int value)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (6, "image_write_b (%02x)\n", (int) value);
-#endif
-
- if (PRIV (is_vax) && check_section (abfd, 1))
- return;
-
- if (PRIV (dst_section))
- dst_check_allocation (abfd, 1);
-
- *PRIV (image_ptr)++ = (value & 0xff);
-}
-
-/* Write 2-byte word to image. */
-
-static void
-image_write_w (bfd * abfd, unsigned int value)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (6, "image_write_w (%04x)\n", (int) value);
-#endif
-
- 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;
-}
-
-/* Write 4-byte long to image. */
-
-static void
-image_write_l (bfd * abfd, unsigned long value)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (6, "image_write_l (%08lx)\n", value);
-#endif
-
- 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;
-}
-
-/* Write 8-byte quad to image. */
-
-static void
-image_write_q (bfd * abfd, uquad value)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (6, "image_write_q (%016lx)\n", value);
-#endif
-
- 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;
-}
-\f
-static const char *
-cmd_name (int cmd)
-{
- switch (cmd)
- {
- case ETIR_S_C_STA_GBL: return "ETIR_S_C_STA_GBL";
- case ETIR_S_C_STA_LW: return "ETIR_S_C_STA_LW";
- case ETIR_S_C_STA_QW: return "ETIR_S_C_STA_QW";
- case ETIR_S_C_STA_PQ: return "ETIR_S_C_STA_PQ";
- case ETIR_S_C_STA_LI: return "ETIR_S_C_STA_LI";
- case ETIR_S_C_STA_MOD: return "ETIR_S_C_STA_MOD";
- case ETIR_S_C_STA_CKARG: return "ETIR_S_C_STA_CKARG";
- case ETIR_S_C_STO_B: return "ETIR_S_C_STO_B";
- case ETIR_S_C_STO_W: return "ETIR_S_C_STO_W";
- case ETIR_S_C_STO_GBL: return "ETIR_S_C_STO_GBL";
- 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_OPR_REDEF: return "ETIR_S_C_OPR_REDEF";
- case ETIR_S_C_OPR_DFLIT: return "ETIR_S_C_OPR_DFLIT";
- case ETIR_S_C_STC_LP: return "ETIR_S_C_STC_LP";
- case ETIR_S_C_STC_GBL: return "ETIR_S_C_STC_GBL";
- case ETIR_S_C_STC_GCA: return "ETIR_S_C_STC_GCA";
- case ETIR_S_C_STC_PS: return "ETIR_S_C_STC_PS";
- case ETIR_S_C_STC_NBH_PS: return "ETIR_S_C_STC_NBH_PS";
- case ETIR_S_C_STC_NOP_GBL: return "ETIR_S_C_STC_NOP_GBL";
- case ETIR_S_C_STC_NOP_PS: return "ETIR_S_C_STC_NOP_PS";
- case ETIR_S_C_STC_BSR_GBL: return "ETIR_S_C_STC_BSR_GBL";
- case ETIR_S_C_STC_BSR_PS: return "ETIR_S_C_STC_BSR_PS";
- case ETIR_S_C_STC_LDA_GBL: return "ETIR_S_C_STC_LDA_GBL";
- case ETIR_S_C_STC_LDA_PS: return "ETIR_S_C_STC_LDA_PS";
- case ETIR_S_C_STC_BOH_GBL: return "ETIR_S_C_STC_BOH_GBL";
- case ETIR_S_C_STC_BOH_PS: return "ETIR_S_C_STC_BOH_PS";
- case ETIR_S_C_STC_NBH_GBL: return "ETIR_S_C_STC_NBH_GBL";
- case ETIR_S_C_CTL_SETRB: return "ETIR_S_C_CTL_SETRB";
- case ETIR_S_C_STC_LP_PSB: return "ETIR_S_C_STC_LP_PSB";
- case ETIR_S_C_CTL_DFLOC: return "ETIR_S_C_CTL_DFLOC";
- case ETIR_S_C_CTL_STLOC: return "ETIR_S_C_CTL_STLOC";
- case ETIR_S_C_CTL_STKDL: return "ETIR_S_C_CTL_STKDL";
-
- default:
- /* These names have not yet been added to this switch statement. */
- (*_bfd_error_handler) (_("unknown ETIR command %d"), cmd);
- }
-
- return NULL;
-}
-#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
-
-/* etir_sta
-
- Vms stack commands.
-
- Handle sta_xxx commands in etir section,
- ptr points to data area in record.
-
- See table B-8 of the openVMS linker manual. */
-
-static bfd_boolean
-etir_sta (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (5, "etir_sta %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- switch (cmd)
- {
- /* Stack global
- arg: cs symbol name
-
- stack 32 bit value of symbol (high bits set to 0). */
- case ETIR_S_C_STA_GBL:
- {
- char *name;
- vms_symbol_entry *entry;
-
- name = _bfd_vms_save_counted_string (ptr);
- entry = (vms_symbol_entry *)
- bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
- if (entry == NULL)
- {
-#if VMS_DEBUG
- _bfd_vms_debug (3, "%s: no symbol \"%s\"\n",
- cmd_name (cmd), name);
-#endif
- _bfd_vms_push (abfd, (uquad) 0, -1);
- }
- else
- _bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1);
- }
- *quarter_relocs = 1;
- break;
-
- /* Stack longword
- arg: lw value
-
- stack 32 bit value, sign extend to 64 bit. */
- case ETIR_S_C_STA_LW:
- _bfd_vms_push (abfd, (uquad) bfd_getl32 (ptr), -1);
- /* This one is special as it is both part of the section header
- and of the ALPHA_R_REFLONG relocation. */
- if (bfd_getl16 (ptr - 4 + bfd_getl16 (ptr - 2)) == ETIR_S_C_CTL_DFLOC)
- *quarter_relocs = 0;
- else if (*quarter_relocs)
- *quarter_relocs += 1;
- else
- *quarter_relocs = 2;
- break;
-
- /* Stack quadword
- arg: qw value
-
- stack 64 bit value of symbol. */
- case ETIR_S_C_STA_QW:
- _bfd_vms_push (abfd, (uquad) bfd_getl64 (ptr), -1);
- if (*quarter_relocs)
- *quarter_relocs += 1;
- else
- *quarter_relocs = 2;
- break;
-
- /* Stack psect base plus quadword offset
- arg: lw section index
- qw signed quadword offset (low 32 bits)
-
- Stack qw argument and section index
- (see ETIR_S_C_STO_OFF, ETIR_S_C_CTL_SETRB). */
- case ETIR_S_C_STA_PQ:
- {
- uquad dummy;
- int psect;
-
- psect = bfd_getl32 (ptr);
- if ((unsigned int) psect >= PRIV (section_count))
- {
- (*_bfd_error_handler) (_("bad section index in %s"),
- cmd_name (cmd));
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- dummy = bfd_getl64 (ptr + 4);
- _bfd_vms_push (abfd, dummy, (int) psect);
- }
- /* This one is special as it is both part of the section header
- and of the ALPHA_R_REFLONG and ALPHA_R_REFQUAD relocations. */
- if (bfd_getl16 (ptr - 4 + bfd_getl16 (ptr - 2)) == ETIR_S_C_CTL_SETRB)
- *quarter_relocs = 0;
- else
- *quarter_relocs = 2;
- break;
-
- case ETIR_S_C_STA_LI:
- case ETIR_S_C_STA_MOD:
- case ETIR_S_C_STA_CKARG:
- (*_bfd_error_handler) (_("unsupported STA cmd %s"), cmd_name (cmd));
- *quarter_relocs = 0;
- return FALSE;
-
- default:
- (*_bfd_error_handler) (_("reserved STA cmd %d"), cmd);
- *quarter_relocs = 0;
- return FALSE;
- }
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "etir_sta true\n");
-#endif
-
- return TRUE;
-}
-
-/* etir_sto
-
- vms store commands
-
- handle sto_xxx commands in etir section
- ptr points to data area in record
-
- see table B-9 of the openVMS linker manual. */
-
-static bfd_boolean
-etir_sto (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
-{
- uquad dummy;
- int psect;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "etir_sto %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- switch (cmd)
- {
- /* Store byte: pop stack, write byte
- arg: -. */
- case ETIR_S_C_STO_B:
- 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
- arg: -. */
- case ETIR_S_C_STO_W:
- 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
- arg: -. */
- case ETIR_S_C_STO_LW:
- dummy = _bfd_vms_pop (abfd, &psect);
- 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
- arg: -. */
- case ETIR_S_C_STO_QW:
- dummy = _bfd_vms_pop (abfd, &psect);
- 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
- arg: lw byte count
- da data. */
- case ETIR_S_C_STO_IMMR:
- {
- int size;
-
- size = bfd_getl32 (ptr);
- dummy = (unsigned long) _bfd_vms_pop (abfd, NULL);
- while (dummy-- > 0)
- image_dump (abfd, ptr+4, size, 0);
- }
- *quarter_relocs = 0;
- break;
-
- /* Store global: write symbol value
- arg: cs global symbol name. */
- case ETIR_S_C_STO_GBL:
- {
- vms_symbol_entry *entry;
- char *name;
-
- name = _bfd_vms_save_counted_string (ptr);
- entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
- name, FALSE, FALSE);
- if (entry == NULL)
- /* FIXME, reloc. */
- image_write_q (abfd, (uquad) (0));
- else
- /* FIXME, reloc. */
- image_write_q (abfd, (uquad) (entry->symbol->value));
- }
- *quarter_relocs = 4;
- break;
-
- /* Store code address: write address of entry point
- arg: cs global symbol name (procedure). */
- case ETIR_S_C_STO_CA:
- {
- vms_symbol_entry *entry;
- char *name;
-
- name = _bfd_vms_save_counted_string (ptr);
- entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
- name, FALSE, FALSE);
- if (entry == NULL)
- /* FIXME, reloc. */
- image_write_q (abfd, (uquad) (0));
- else
- /* FIXME, reloc. */
- image_write_q (abfd, (uquad) (entry->symbol->value));
- }
- *quarter_relocs = 4;
- break;
-
- /* Store offset to psect: pop stack, add low 32 bits to base of psect
- arg: none. */
- case ETIR_S_C_STO_OFF:
- {
- uquad q;
- int psect1;
-
- q = _bfd_vms_pop (abfd, & psect1);
- q += (PRIV (sections)[psect1])->vma;
- image_write_q (abfd, q);
- }
- *quarter_relocs += 2;
- break;
-
- /* Store immediate
- arg: lw count of bytes
- da data. */
- case ETIR_S_C_STO_IMM:
- {
- int size;
-
- 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
- linker manual, however it is generated by the DEC C compiler
- and defined in the include file.
- FIXME, since the following is just a guess
- store global longword: store 32bit value of symbol
- arg: cs symbol name. */
- case ETIR_S_C_STO_GBL_LW:
- {
- vms_symbol_entry *entry;
- char *name;
-
- name = _bfd_vms_save_counted_string (ptr);
- entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
- name, FALSE, FALSE);
- if (entry == NULL)
- {
-#if VMS_DEBUG
- _bfd_vms_debug (3, "%s: no symbol \"%s\"\n", cmd_name (cmd), name);
-#endif
- image_write_l (abfd, (unsigned long) 0); /* FIXME, reloc */
- }
- else
- /* FIXME, reloc. */
- image_write_l (abfd, (unsigned long) (entry->symbol->value));
- }
- *quarter_relocs = 4;
- break;
-
- case ETIR_S_C_STO_RB:
- case ETIR_S_C_STO_AB:
- case ETIR_S_C_STO_LP_PSB:
- (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd));
- *quarter_relocs = 0;
- return FALSE;
-
- case ETIR_S_C_STO_HINT_GBL:
- case ETIR_S_C_STO_HINT_PS:
- (*_bfd_error_handler) (_("%s: not implemented"), cmd_name (cmd));
- *quarter_relocs = 0;
- return FALSE;
-
- default:
- (*_bfd_error_handler) (_("reserved STO cmd %d"), cmd);
- *quarter_relocs = 0;
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Stack operator commands
- all 32 bit signed arithmetic
- all word just like a stack calculator
- arguments are popped from stack, results are pushed on stack
-
- see table B-10 of the openVMS linker manual. */
-
-static bfd_boolean
-etir_opr (bfd *abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED,
- int *quarter_relocs)
-{
- long op1, op2;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "etir_opr %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- /* No relocation uses OPR commands except ETIR_S_C_OPR_ADD. */
- if (cmd == ETIR_S_C_OPR_ADD)
- *quarter_relocs += 1;
- else
- *quarter_relocs = 0;
-
- switch (cmd)
- {
- case ETIR_S_C_OPR_NOP: /* No-op. */
- break;
-
- case ETIR_S_C_OPR_ADD: /* Add. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 + op2), -1);
- break;
-
- case ETIR_S_C_OPR_SUB: /* Subtract. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op2 - op1), -1);
- break;
-
- case ETIR_S_C_OPR_MUL: /* Multiply. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 * op2), -1);
- break;
-
- case ETIR_S_C_OPR_DIV: /* Divide. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- if (op2 == 0)
- _bfd_vms_push (abfd, (uquad) 0, -1);
- else
- _bfd_vms_push (abfd, (uquad) (op2 / op1), -1);
- break;
-
- case ETIR_S_C_OPR_AND: /* Logical AND. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 & op2), -1);
- break;
-
- case ETIR_S_C_OPR_IOR: /* Logical inclusive OR. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 | op2), -1);
- break;
-
- case ETIR_S_C_OPR_EOR: /* Logical exclusive OR. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 ^ op2), -1);
- break;
-
- case ETIR_S_C_OPR_NEG: /* Negate. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (-op1), -1);
- break;
-
- case ETIR_S_C_OPR_COM: /* Complement. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 ^ -1L), -1);
- break;
-
- case ETIR_S_C_OPR_ASH: /* Arithmetic shift. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- if (op2 < 0) /* Shift right. */
- op1 >>= -op2;
- else /* Shift left. */
- op1 <<= op2;
- _bfd_vms_push (abfd, (uquad) op1, -1);
- break;
-
- case ETIR_S_C_OPR_INSV: /* Insert field. */
- (void) _bfd_vms_pop (abfd, NULL);
- case ETIR_S_C_OPR_USH: /* Unsigned shift. */
- case ETIR_S_C_OPR_ROT: /* Rotate. */
- case ETIR_S_C_OPR_REDEF: /* Redefine symbol to current location. */
- case ETIR_S_C_OPR_DFLIT: /* Define a literal. */
- (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd));
- return FALSE;
-
- case ETIR_S_C_OPR_SEL: /* Select. */
- if ((long) _bfd_vms_pop (abfd, NULL) & 0x01L)
- (void) _bfd_vms_pop (abfd, NULL);
- else
- {
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- (void) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) op1, -1);
- }
- break;
-
- default:
- (*_bfd_error_handler) (_("reserved OPR cmd %d"), cmd);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Control commands.
-
- See table B-11 of the openVMS linker manual. */
-
-static bfd_boolean
-etir_ctl (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
-{
- uquad dummy;
- int psect;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "etir_ctl %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- /* No relocation uses CTL commands. */
- *quarter_relocs = 0;
-
- switch (cmd)
- {
- /* Det relocation base: pop stack, set image location counter
- arg: none. */
- case ETIR_S_C_CTL_SETRB:
- dummy = _bfd_vms_pop (abfd, &psect);
- image_set_ptr (abfd, psect, dummy);
- break;
-
- /* Augment relocation base: increment image location counter by offset
- arg: lw offset value. */
- case ETIR_S_C_CTL_AUGRB:
- dummy = bfd_getl32 (ptr);
- image_inc_ptr (abfd, dummy);
- break;
-
- /* Define location: pop index, save location counter under index
- arg: none. */
- case ETIR_S_C_CTL_DFLOC:
- dummy = _bfd_vms_pop (abfd, NULL);
- dst_define_location (abfd, dummy);
- break;
-
- /* Set location: pop index, restore location counter from index
- arg: none. */
- case ETIR_S_C_CTL_STLOC:
- dummy = _bfd_vms_pop (abfd, NULL);
- dst_restore_location (abfd, dummy);
- break;
-
- /* Stack defined location: pop index, push location counter from index
- arg: none. */
- case ETIR_S_C_CTL_STKDL:
- dummy = _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, dst_retrieve_location (abfd, dummy), -1);
- break;
-
- default:
- (*_bfd_error_handler) (_("reserved CTL cmd %d"), cmd);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Store conditional commands
-
- See table B-12 and B-13 of the openVMS linker manual. */
-
-static bfd_boolean
-etir_stc (bfd *abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED,
- int *quarter_relocs)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (5, "etir_stc %d/%x\n", cmd, cmd);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- switch (cmd)
- {
- /* 200 Store-conditional Linkage Pair
- arg: none. */
- case ETIR_S_C_STC_LP:
-
- /* 202 Store-conditional Address at global address
- arg: lw linkage index
- cs global name. */
-
- case ETIR_S_C_STC_GBL:
-
- /* 203 Store-conditional Code Address at global address
- arg: lw linkage index
- cs procedure name. */
- case ETIR_S_C_STC_GCA:
-
- /* 204 Store-conditional Address at psect + offset
- arg: lw linkage index
- lw psect 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:
- /* ALPHA_R_NOP */
-
- /* 207 Store-conditional BSR at global address
- arg: none. */
-
- case ETIR_S_C_STC_BSR_GBL:
- /* ALPHA_R_BSR */
-
- /* 209 Store-conditional LDA at global address
- arg: none. */
-
- case ETIR_S_C_STC_LDA_GBL:
- /* ALPHA_R_LDA */
-
- /* 211 Store-conditional BSR or Hint at global address
- arg: none. */
-
- case ETIR_S_C_STC_BOH_GBL:
- *quarter_relocs = 4;
- break;
-
- /* 213 Store-conditional NOP,BSR or HINT at global address
- arg: none. */
-
- case ETIR_S_C_STC_NBH_GBL:
-
- /* 206 Store-conditional NOP at pect + offset
- arg: none. */
-
- case ETIR_S_C_STC_NOP_PS:
-
- /* 208 Store-conditional BSR at pect + offset
- arg: none. */
-
- case ETIR_S_C_STC_BSR_PS:
-
- /* 210 Store-conditional LDA at psect + offset
- arg: none. */
-
- case ETIR_S_C_STC_LDA_PS:
-
- /* 212 Store-conditional BSR or Hint at pect + offset
- arg: none. */
-
- case ETIR_S_C_STC_BOH_PS:
-
- /* 214 Store-conditional NOP, BSR or HINT at psect + offset
- arg: none. */
- case ETIR_S_C_STC_NBH_PS:
- (*_bfd_error_handler) ("%s: not supported", cmd_name (cmd));
- *quarter_relocs = 0;
- return FALSE;
-
- default:
- (*_bfd_error_handler) (_("reserved STC cmd %d"), cmd);
- *quarter_relocs = 0;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static asection *
-new_section (bfd * abfd ATTRIBUTE_UNUSED, int idx)
-{
- asection *section;
- char sname[16];
- char *name;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "new_section %d\n", idx);
-#endif
- sprintf (sname, SECTION_NAME_TEMPLATE, idx);
-
- name = bfd_malloc ((bfd_size_type) strlen (sname) + 1);
- if (name == 0)
- return NULL;
- strcpy (name, sname);
-
- section = bfd_malloc ((bfd_size_type) sizeof (asection));
- if (section == 0)
- {
-#if VMS_DEBUG
- _bfd_vms_debug (6, "new_section (%s) failed", name);
-#endif
- return NULL;
- }
-
- section->size = 0;
- section->vma = 0;
- section->contents = 0;
- section->name = name;
- section->index = idx;
-
- return section;
-}
-
-static int
-alloc_section (bfd * abfd, unsigned int idx)
-{
- bfd_size_type amt;
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "alloc_section %d\n", idx);
-#endif
-
- amt = idx + 1;
- amt *= sizeof (asection *);
- PRIV (sections) = bfd_realloc_or_free (PRIV (sections), amt);
- if (PRIV (sections) == NULL)
- return -1;
-
- while (PRIV (section_count) <= idx)
- {
- PRIV (sections)[PRIV (section_count)]
- = new_section (abfd, (int) PRIV (section_count));
- if (PRIV (sections)[PRIV (section_count)] == 0)
- return -1;
- PRIV (section_count)++;
- }
-
- return 0;
-}
-
-/* tir_sta
-
- Vax stack commands.
-
- Handle sta_xxx commands in tir section,
- ptr points to data area in record.
-
- See table 7-3 of the VAX/VMS linker manual. */
-
-static unsigned char *
-tir_sta (bfd * abfd, unsigned char *ptr)
-{
- int cmd = *ptr++;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "tir_sta %d\n", cmd);
-#endif
-
- switch (cmd)
- {
- /* stack */
- case TIR_S_C_STA_GBL:
- /* stack global
- arg: cs symbol name
-
- stack 32 bit value of symbol (high bits set to 0). */
- {
- char *name;
- vms_symbol_entry *entry;
-
- name = _bfd_vms_save_counted_string (ptr);
-
- entry = _bfd_vms_enter_symbol (abfd, name);
- if (entry == NULL)
- return NULL;
-
- _bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1);
- ptr += *ptr + 1;
- }
- break;
-
- case TIR_S_C_STA_SB:
- /* stack signed byte
- arg: by value
-
- stack byte value, sign extend to 32 bit. */
- _bfd_vms_push (abfd, (uquad) *ptr++, -1);
- break;
-
- case TIR_S_C_STA_SW:
- /* stack signed short word
- arg: sh value
-
- stack 16 bit value, sign extend to 32 bit. */
- _bfd_vms_push (abfd, (uquad) bfd_getl16 (ptr), -1);
- ptr += 2;
- break;
-
- case TIR_S_C_STA_LW:
- /* stack signed longword
- arg: lw value
-
- stack 32 bit value. */
- _bfd_vms_push (abfd, (uquad) bfd_getl32 (ptr), -1);
- ptr += 4;
- break;
-
- case TIR_S_C_STA_PB:
- case TIR_S_C_STA_WPB:
- /* stack psect base plus byte offset (word index)
- arg: by section index
- (sh section index)
- by signed byte offset. */
- {
- unsigned long dummy;
- int psect;
-
- if (cmd == TIR_S_C_STA_PB)
- psect = *ptr++;
- else
- {
- psect = bfd_getl16 (ptr);
- ptr += 2;
- }
-
- if ((unsigned int) psect >= PRIV (section_count))
- alloc_section (abfd, psect);
-
- dummy = (long) *ptr++;
- dummy += (PRIV (sections)[psect])->vma;
- _bfd_vms_push (abfd, (uquad) dummy, psect);
- }
- break;
-
- case TIR_S_C_STA_PW:
- case TIR_S_C_STA_WPW:
- /* stack psect base plus word offset (word index)
- arg: by section index
- (sh section index)
- sh signed short offset. */
- {
- unsigned long dummy;
- int psect;
-
- if (cmd == TIR_S_C_STA_PW)
- psect = *ptr++;
- else
- {
- psect = bfd_getl16 (ptr);
- ptr += 2;
- }
-
- if ((unsigned int) psect >= PRIV (section_count))
- alloc_section (abfd, psect);
-
- dummy = bfd_getl16 (ptr); ptr+=2;
- dummy += (PRIV (sections)[psect])->vma;
- _bfd_vms_push (abfd, (uquad) dummy, psect);
- }
- break;
-
- case TIR_S_C_STA_PL:
- case TIR_S_C_STA_WPL:
- /* stack psect base plus long offset (word index)
- arg: by section index
- (sh section index)
- lw signed longword offset. */
- {
- unsigned long dummy;
- int psect;
-
- if (cmd == TIR_S_C_STA_PL)
- psect = *ptr++;
- else
- {
- psect = bfd_getl16 (ptr);
- ptr += 2;
- }
-
- if ((unsigned int) psect >= PRIV (section_count))
- alloc_section (abfd, psect);
-
- dummy = bfd_getl32 (ptr); ptr += 4;
- dummy += (PRIV (sections)[psect])->vma;
- _bfd_vms_push (abfd, (uquad) dummy, psect);
- }
- break;
-
- case TIR_S_C_STA_UB:
- /* stack unsigned byte
- arg: by value
-
- stack byte value. */
- _bfd_vms_push (abfd, (uquad) *ptr++, -1);
- break;
-
- case TIR_S_C_STA_UW:
- /* stack unsigned short word
- arg: sh value
-
- stack 16 bit value. */
- _bfd_vms_push (abfd, (uquad) bfd_getl16 (ptr), -1);
- ptr += 2;
- break;
-
- case TIR_S_C_STA_BFI:
- /* stack byte from image
- arg: none. */
- /* FALLTHRU */
- case TIR_S_C_STA_WFI:
- /* stack byte from image
- arg: none. */
- /* FALLTHRU */
- case TIR_S_C_STA_LFI:
- /* stack byte from image
- arg: none. */
- (*_bfd_error_handler) (_("stack-from-image not implemented"));
- return NULL;
-
- case TIR_S_C_STA_EPM:
- /* stack entry point mask
- arg: cs symbol name
-
- stack (unsigned) entry point mask of symbol
- err if symbol is no entry point. */
- {
- char *name;
- vms_symbol_entry *entry;
-
- name = _bfd_vms_save_counted_string (ptr);
- entry = _bfd_vms_enter_symbol (abfd, name);
- if (entry == NULL)
- return NULL;
-
- (*_bfd_error_handler) (_("stack-entry-mask not fully implemented"));
- _bfd_vms_push (abfd, (uquad) 0, -1);
- ptr += *ptr + 1;
- }
- break;
-
- case TIR_S_C_STA_CKARG:
- /* compare procedure argument
- arg: cs symbol name
- by argument index
- da argument descriptor
-
- compare argument descriptor with symbol argument (ARG$V_PASSMECH)
- and stack TRUE (args match) or FALSE (args dont match) value. */
- (*_bfd_error_handler) (_("PASSMECH not fully implemented"));
- _bfd_vms_push (abfd, (uquad) 1, -1);
- break;
-
- case TIR_S_C_STA_LSY:
- /* stack local symbol value
- arg: sh environment index
- cs symbol name. */
- {
- int envidx;
- char *name;
- vms_symbol_entry *entry;
-
- envidx = bfd_getl16 (ptr);
- ptr += 2;
- name = _bfd_vms_save_counted_string (ptr);
- entry = _bfd_vms_enter_symbol (abfd, name);
- if (entry == NULL)
- return NULL;
- (*_bfd_error_handler) (_("stack-local-symbol not fully implemented"));
- _bfd_vms_push (abfd, (uquad) 0, -1);
- ptr += *ptr + 1;
- }
- break;
-
- case TIR_S_C_STA_LIT:
- /* stack literal
- arg: by literal index
-
- stack literal. */
- ptr++;
- _bfd_vms_push (abfd, (uquad) 0, -1);
- (*_bfd_error_handler) (_("stack-literal not fully implemented"));
- break;
-
- case TIR_S_C_STA_LEPM:
- /* stack local symbol entry point mask
- arg: sh environment index
- cs symbol name
-
- stack (unsigned) entry point mask of symbol
- err if symbol is no entry point. */
- {
- int envidx;
- char *name;
- vms_symbol_entry *entry;
-
- envidx = bfd_getl16 (ptr);
- ptr += 2;
- name = _bfd_vms_save_counted_string (ptr);
- entry = _bfd_vms_enter_symbol (abfd, name);
- if (entry == NULL)
- return NULL;
- (*_bfd_error_handler) (_("stack-local-symbol-entry-point-mask not fully implemented"));
- _bfd_vms_push (abfd, (uquad) 0, -1);
- ptr += *ptr + 1;
- }
- break;
-
- default:
- (*_bfd_error_handler) (_("reserved STA cmd %d"), ptr[-1]);
- return NULL;
- break;
- }
-
- return ptr;
-}
-
-static const char *
-tir_cmd_name (int cmd)
-{
- switch (cmd)
- {
- case TIR_S_C_STO_RSB: return "TIR_S_C_STO_RSB";
- case TIR_S_C_STO_RSW: return "TIR_S_C_STO_RSW";
- case TIR_S_C_STO_RL: return "TIR_S_C_STO_RL";
- case TIR_S_C_STO_VPS: return "TIR_S_C_STO_VPS";
- case TIR_S_C_STO_USB: return "TIR_S_C_STO_USB";
- case TIR_S_C_STO_USW: return "TIR_S_C_STO_USW";
- case TIR_S_C_STO_RUB: return "TIR_S_C_STO_RUB";
- case TIR_S_C_STO_RUW: return "TIR_S_C_STO_RUW";
- case TIR_S_C_STO_PIRR: return "TIR_S_C_STO_PIRR";
- case TIR_S_C_OPR_INSV: return "TIR_S_C_OPR_INSV";
- case TIR_S_C_OPR_DFLIT: return "TIR_S_C_OPR_DFLIT";
- case TIR_S_C_OPR_REDEF: return "TIR_S_C_OPR_REDEF";
- case TIR_S_C_OPR_ROT: return "TIR_S_C_OPR_ROT";
- case TIR_S_C_OPR_USH: return "TIR_S_C_OPR_USH";
- case TIR_S_C_OPR_ASH: return "TIR_S_C_OPR_ASH";
- case TIR_S_C_CTL_DFLOC: return "TIR_S_C_CTL_DFLOC";
- case TIR_S_C_CTL_STLOC: return "TIR_S_C_CTL_STLOC";
- case TIR_S_C_CTL_STKDL: return "TIR_S_C_CTL_STKDL";
-
- default:
- /* These strings have not been added yet. */
- abort ();
- }
-}
-
-/* tir_sto
-
- vax store commands
-
- handle sto_xxx commands in tir section
- ptr points to data area in record
-
- See table 7-4 of the VAX/VMS linker manual. */
-
-static unsigned char *
-tir_sto (bfd * abfd, unsigned char *ptr)
-{
- unsigned long dummy;
- int size;
- int psect;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "tir_sto %d\n", *ptr);
-#endif
-
- switch (*ptr++)
- {
- case TIR_S_C_STO_SB:
- /* Store signed byte: pop stack, write byte
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- image_write_b (abfd, dummy & 0xff); /* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_SW:
- /* Store signed word: pop stack, write word
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- image_write_w (abfd, dummy & 0xffff); /* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_LW:
- /* Store longword: pop stack, write longword
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- image_write_l (abfd, dummy & 0xffffffff); /* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_BD:
- /* Store byte displaced: pop stack, sub lc+1, write byte
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- dummy -= ((PRIV (sections)[psect])->vma + 1);
- image_write_b (abfd, dummy & 0xff);/* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_WD:
- /* Store word displaced: pop stack, sub lc+2, write word
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- dummy -= ((PRIV (sections)[psect])->vma + 2);
- image_write_w (abfd, dummy & 0xffff);/* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_LD:
- /* Store long displaced: pop stack, sub lc+4, write long
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- dummy -= ((PRIV (sections)[psect])->vma + 4);
- image_write_l (abfd, dummy & 0xffffffff);/* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_LI:
- /* Store short literal: pop stack, write byte
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- image_write_b (abfd, dummy & 0xff);/* FIXME: check top bits */
- break;
-
- case TIR_S_C_STO_PIDR:
- /* Store position independent data reference: pop stack, write longword
- arg: none.
- FIXME: incomplete ! */
- dummy = _bfd_vms_pop (abfd, &psect);
- image_write_l (abfd, dummy & 0xffffffff);
- break;
-
- case TIR_S_C_STO_PICR:
- /* Store position independent code reference: pop stack, write longword
- arg: none.
- FIXME: incomplete ! */
- dummy = _bfd_vms_pop (abfd, &psect);
- image_write_b (abfd, 0x9f);
- image_write_l (abfd, dummy & 0xffffffff);
- break;
-
- case TIR_S_C_STO_RIVB:
- /* Store repeated immediate variable bytes
- 1-byte count n field followed by n bytes of data
- pop stack, write n bytes <stack> times. */
- size = *ptr++;
- dummy = (unsigned long) _bfd_vms_pop (abfd, NULL);
- while (dummy-- > 0L)
- image_dump (abfd, ptr, size, 0);
- ptr += size;
- break;
-
- case TIR_S_C_STO_B:
- /* Store byte from top longword. */
- dummy = (unsigned long) _bfd_vms_pop (abfd, NULL);
- image_write_b (abfd, dummy & 0xff);
- break;
-
- case TIR_S_C_STO_W:
- /* Store word from top longword. */
- dummy = (unsigned long) _bfd_vms_pop (abfd, NULL);
- image_write_w (abfd, dummy & 0xffff);
- break;
-
- case TIR_S_C_STO_RB:
- /* Store repeated byte from top longword. */
- size = (unsigned long) _bfd_vms_pop (abfd, NULL);
- dummy = (unsigned long) _bfd_vms_pop (abfd, NULL);
- while (size-- > 0)
- image_write_b (abfd, dummy & 0xff);
- break;
-
- case TIR_S_C_STO_RW:
- /* Store repeated word from top longword. */
- size = (unsigned long) _bfd_vms_pop (abfd, NULL);
- dummy = (unsigned long) _bfd_vms_pop (abfd, NULL);
- while (size-- > 0)
- image_write_w (abfd, dummy & 0xffff);
- break;
-
- case TIR_S_C_STO_RSB:
- case TIR_S_C_STO_RSW:
- case TIR_S_C_STO_RL:
- case TIR_S_C_STO_VPS:
- case TIR_S_C_STO_USB:
- case TIR_S_C_STO_USW:
- case TIR_S_C_STO_RUB:
- case TIR_S_C_STO_RUW:
- case TIR_S_C_STO_PIRR:
- (*_bfd_error_handler) (_("%s: not implemented"), tir_cmd_name (ptr[-1]));
- break;
-
- default:
- (*_bfd_error_handler) (_("reserved STO cmd %d"), ptr[-1]);
- break;
- }
-
- return ptr;
-}
-
-/* Stack operator commands
- All 32 bit signed arithmetic
- All word just like a stack calculator
- Arguments are popped from stack, results are pushed on stack
-
- See table 7-5 of the VAX/VMS linker manual. */
-
-static unsigned char *
-tir_opr (bfd * abfd, unsigned char *ptr)
-{
- long op1, op2;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "tir_opr %d\n", *ptr);
-#endif
-
- /* Operation. */
- switch (*ptr++)
- {
- case TIR_S_C_OPR_NOP: /* No-op. */
- break;
-
- case TIR_S_C_OPR_ADD: /* Add. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 + op2), -1);
- break;
-
- case TIR_S_C_OPR_SUB: /* Subtract. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op2 - op1), -1);
- break;
-
- case TIR_S_C_OPR_MUL: /* Multiply. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 * op2), -1);
- break;
-
- case TIR_S_C_OPR_DIV: /* Divide. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- if (op2 == 0)
- _bfd_vms_push (abfd, (uquad) 0, -1);
- else
- _bfd_vms_push (abfd, (uquad) (op2 / op1), -1);
- break;
-
- case TIR_S_C_OPR_AND: /* Logical AND. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 & op2), -1);
- break;
-
- case TIR_S_C_OPR_IOR: /* Logical inclusive OR. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 | op2), -1);
- break;
-
- case TIR_S_C_OPR_EOR: /* Logical exclusive OR. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 ^ op2), -1);
- break;
-
- case TIR_S_C_OPR_NEG: /* Negate. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (-op1), -1);
- break;
-
- case TIR_S_C_OPR_COM: /* Complement. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) (op1 ^ -1L), -1);
- break;
-
- case TIR_S_C_OPR_INSV: /* Insert field. */
- (void) _bfd_vms_pop (abfd, NULL);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- case TIR_S_C_OPR_ASH: /* Arithmetic shift. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- if (HIGHBIT (op1)) /* Shift right. */
- op2 >>= op1;
- else /* Shift left. */
- op2 <<= op1;
- _bfd_vms_push (abfd, (uquad) op2, -1);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- case TIR_S_C_OPR_USH: /* Unsigned shift. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- if (HIGHBIT (op1)) /* Shift right. */
- op2 >>= op1;
- else /* Shift left. */
- op2 <<= op1;
- _bfd_vms_push (abfd, (uquad) op2, -1);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- case TIR_S_C_OPR_ROT: /* Rotate. */
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- op2 = (long) _bfd_vms_pop (abfd, NULL);
- if (HIGHBIT (0)) /* Shift right. */
- op2 >>= op1;
- else /* Shift left. */
- op2 <<= op1;
- _bfd_vms_push (abfd, (uquad) op2, -1);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- case TIR_S_C_OPR_SEL: /* Select. */
- if ((long) _bfd_vms_pop (abfd, NULL) & 0x01L)
- (void) _bfd_vms_pop (abfd, NULL);
- else
- {
- op1 = (long) _bfd_vms_pop (abfd, NULL);
- (void) _bfd_vms_pop (abfd, NULL);
- _bfd_vms_push (abfd, (uquad) op1, -1);
- }
- break;
-
- case TIR_S_C_OPR_REDEF: /* Redefine symbol to current location. */
- case TIR_S_C_OPR_DFLIT: /* Define a literal. */
- (*_bfd_error_handler) (_("%s: not supported"),
- tir_cmd_name (ptr[-1]));
- break;
-
- default:
- (*_bfd_error_handler) (_("reserved OPR cmd %d"), ptr[-1]);
- break;
- }
-
- return ptr;
-}
-
-/* Control commands
-
- See table 7-6 of the VAX/VMS linker manual. */
-
-static unsigned char *
-tir_ctl (bfd * abfd, unsigned char *ptr)
-{
- unsigned long dummy;
- int psect;
-
-#if VMS_DEBUG
- _bfd_vms_debug (5, "tir_ctl %d\n", *ptr);
-#endif
-
- switch (*ptr++)
- {
- case TIR_S_C_CTL_SETRB:
- /* Set relocation base: pop stack, set image location counter
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- if ((unsigned int) psect >= PRIV (section_count))
- alloc_section (abfd, psect);
- image_set_ptr (abfd, psect, (uquad) dummy);
- break;
-
- case TIR_S_C_CTL_AUGRB:
- /* Augment relocation base: increment image location counter by offset
- arg: lw offset value. */
- dummy = bfd_getl32 (ptr);
- image_inc_ptr (abfd, (uquad) dummy);
- break;
-
- case TIR_S_C_CTL_DFLOC:
- /* Define location: pop index, save location counter under index
- arg: none. */
- dummy = _bfd_vms_pop (abfd, NULL);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- case TIR_S_C_CTL_STLOC:
- /* Set location: pop index, restore location counter from index
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- case TIR_S_C_CTL_STKDL:
- /* Stack defined location: pop index, push location counter from index
- arg: none. */
- dummy = _bfd_vms_pop (abfd, &psect);
- (*_bfd_error_handler) (_("%s: not fully implemented"),
- tir_cmd_name (ptr[-1]));
- break;
-
- default:
- (*_bfd_error_handler) (_("reserved CTL cmd %d"), ptr[-1]);
- break;
- }
- return ptr;
-}
-
-/* Handle command from TIR section. */
-
-static unsigned char *
-tir_cmd (bfd * abfd, unsigned char *ptr)
-{
- static const struct
- {
- int mincod;
- int maxcod;
- unsigned char * (*explain) (bfd *, unsigned char *);
- }
- tir_table[] =
- {
- { 0, TIR_S_C_MAXSTACOD, tir_sta },
- { TIR_S_C_MINSTOCOD, TIR_S_C_MAXSTOCOD, tir_sto },
- { TIR_S_C_MINOPRCOD, TIR_S_C_MAXOPRCOD, tir_opr },
- { TIR_S_C_MINCTLCOD, TIR_S_C_MAXCTLCOD, tir_ctl },
- { -1, -1, NULL }
- };
- int i = 0;
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "tir_cmd %d/%x\n", *ptr, *ptr);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- if (*ptr & 0x80)
- {
- /* Store immediate. */
- i = 128 - (*ptr++ & 0x7f);
- image_dump (abfd, ptr, i, 0);
- ptr += i;
- }
- else
- {
- while (tir_table[i].mincod >= 0)
- {
- if ( (tir_table[i].mincod <= *ptr)
- && (*ptr <= tir_table[i].maxcod))
- {
- ptr = tir_table[i].explain (abfd, ptr);
- break;
- }
- i++;
- }
- if (tir_table[i].mincod < 0)
- {
- (*_bfd_error_handler) (_("obj code %d not found"), *ptr);
- ptr = 0;
- }
- }
-
- return ptr;
-}
-
-/* Handle command from ETIR section. */
-
-static int
-etir_cmd (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs)
-{
- static const struct
- {
- int mincod;
- int maxcod;
- bfd_boolean (*explain) (bfd *, int, unsigned char *, int *);
- }
- etir_table[] =
- {
- { ETIR_S_C_MINSTACOD, ETIR_S_C_MAXSTACOD, etir_sta },
- { ETIR_S_C_MINSTOCOD, ETIR_S_C_MAXSTOCOD, etir_sto },
- { ETIR_S_C_MINOPRCOD, ETIR_S_C_MAXOPRCOD, etir_opr },
- { ETIR_S_C_MINCTLCOD, ETIR_S_C_MAXCTLCOD, etir_ctl },
- { ETIR_S_C_MINSTCCOD, ETIR_S_C_MAXSTCCOD, etir_stc },
- { -1, -1, NULL }
- };
-
- int i = 0;
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "etir_cmd: %s(%d)\n", cmd_name (cmd), cmd);
- _bfd_hexdump (8, ptr, 16, (long) ptr);
-#endif
-
- while (etir_table[i].mincod >= 0)
- {
- if ( (etir_table[i].mincod <= cmd)
- && (cmd <= etir_table[i].maxcod))
- {
- if (!etir_table[i].explain (abfd, cmd, ptr, quarter_relocs))
- return -1;
- break;
- }
- i++;
- }
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "etir_cmd: result = 0\n");
-#endif
- return 0;
-}
-
-/* Text Information and Relocation Records (OBJ$C_TIR)
- handle tir record. */
-
-static int
-analyze_tir (bfd * abfd, unsigned char *ptr, unsigned int length)
-{
- unsigned char *maxptr;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "analyze_tir: %d bytes\n", length);
-#endif
-
- maxptr = ptr + length;
-
- while (ptr < maxptr)
- {
- ptr = tir_cmd (abfd, ptr);
- if (ptr == 0)
- return -1;
- }
-
- return 0;
-}
-
-/* Text Information and Relocation Records (EOBJ$C_ETIR)
- handle etir record. */
-
-static int
-analyze_etir (bfd * abfd, unsigned char *ptr, unsigned int length)
-{
- unsigned char *maxptr = ptr + length;
- /* Relocations are made of 1, 2 or 4 ETIR commands.
- We therefore count them using quarters. */
- int quarter_relocs = 0;
- int result = 0;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "analyze_etir: %d bytes\n", length);
-#endif
-
- while (ptr < maxptr)
- {
- int cmd = bfd_getl16 (ptr);
- int cmd_length = bfd_getl16 (ptr + 2);
- result = etir_cmd (abfd, cmd, ptr + 4, &quarter_relocs);
- if (result != 0)
- break;
-
- /* If we have a relocation, we record its length to size
- future buffers and bump the reloc count of the section. */
- if (quarter_relocs)
- {
- vms_section_data (PRIV (image_section))->reloc_size += cmd_length;
- abfd->flags |= HAS_RELOC;
-
- if (quarter_relocs == 4)
- {
- PRIV (image_section)->reloc_count++;
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "-> reloc %d at 0x%x\n",
- PRIV (image_section)->reloc_count-1,
- ptr - (maxptr - length));
-#endif
-
- quarter_relocs = 0;
- }
- else if (quarter_relocs > 4)
- {
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "Reloc count error (%d) in section %s\n",
- PRIV (image_section)->reloc_count,
- PRIV (image_section)->name);
-#endif
-
- quarter_relocs = 0;
- }
- }
-
- /* If we have a Store Immediate, we reserve space for the
- count argument. */
- else if (cmd == ETIR_S_C_STO_IMM)
- vms_section_data (PRIV (image_section))->reloc_size
- += ETIR_S_C_HEADER_SIZE + 4;
-
- ptr += cmd_length;
- }
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "analyze_etir: result = %d\n", result);
-#endif
-
- return result;
-}
-
-/* Process ETIR record
- Return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_tir (bfd * abfd, int objtype)
-{
- int result;
-
-#if VMS_DEBUG
- _bfd_vms_debug (2, "TIR/ETIR\n");
-#endif
-
- switch (objtype)
- {
- case EOBJ_S_C_ETIR:
- PRIV (vms_rec) += ETIR_S_C_HEADER_SIZE;
- PRIV (rec_size) -= ETIR_S_C_HEADER_SIZE;
- result = analyze_etir (abfd, PRIV (vms_rec), (unsigned) PRIV (rec_size));
- break;
- case OBJ_S_C_TIR:
- PRIV (vms_rec) += 1; /* Skip type. */
- PRIV (rec_size) -= 1;
- result = analyze_tir (abfd, PRIV (vms_rec), (unsigned) PRIV (rec_size));
- break;
- default:
- result = -1;
- break;
- }
-
- return result;
-}
-
- /* Slurp relocs from ETIR sections and (temporarily) save them
- in the per-section reloc buffer. */
-
-int
-_bfd_vms_slurp_relocs (bfd *abfd)
-{
- struct vms_section_data_struct *vsd;
- unsigned char *begin = PRIV (vms_rec) + 4;
- unsigned char *end = PRIV (vms_rec) + PRIV (rec_size);
- unsigned char *ptr;
- int cmd, length, slurped_length;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "_bfd_vms_slurp_relocs: %d bytes\n", PRIV (rec_size));
-#endif
-
- for (ptr = begin; ptr < end; ptr += length)
- {
- cmd = bfd_getl16 (ptr);
- length = bfd_getl16 (ptr + 2);
- slurped_length = length;
-
- switch (cmd)
- {
- case ETIR_S_C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */
- /* This one is special as it is both part of the section header
- and of the ALPHA_R_REFLONG and ALPHA_R_REFQUAD relocations. */
- if (bfd_getl16 (ptr + length) == ETIR_S_C_CTL_SETRB)
- {
- int psect = bfd_getl32 (ptr + ETIR_S_C_HEADER_SIZE);
- PRIV (image_section) = PRIV (sections)[psect];
- continue;
- }
-
- case ETIR_S_C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */
- /* ALPHA_R_REFQUAD und_section, step 1 */
- break;
-
- case ETIR_S_C_STA_LW: /* ALPHA_R_REFLONG und_section, step 2 */
- /* ALPHA_R_REFLONG abs_section, step 1 */
- /* This one is special as it is both part of the section header
- and of the ALPHA_R_REFLONG relocation. */
- if (bfd_getl16 (ptr + length) == ETIR_S_C_CTL_DFLOC)
- {
- PRIV (image_section) = PRIV (dst_section);
- continue;
- }
-
- case ETIR_S_C_STA_QW: /* ALPHA_R_REFQUAD und_section, step 2 */
- /* ALPHA_R_REFQUAD abs_section, step 1 */
-
- case ETIR_S_C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */
- /* ALPHA_R_REFLONG abs_section, step 2 */
- /* ALPHA_R_REFLONG others, step 2 */
-
- case ETIR_S_C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */
- /* ALPHA_R_REFQUAD abs_section, step 2 */
-
- case ETIR_S_C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */
-
- case ETIR_S_C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */
- /* ALPHA_R_REFQUAD und_section, step 3 */
-
- case ETIR_S_C_STO_CA: /* ALPHA_R_CODEADDR */
- case ETIR_S_C_STO_GBL: /* ALPHA_R_REFQUAD und_section */
- case ETIR_S_C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */
- case ETIR_S_C_STC_LP_PSB: /* ALPHA_R_LINKAGE */
- case ETIR_S_C_STC_NOP_GBL: /* ALPHA_R_NOP */
- case ETIR_S_C_STC_BSR_GBL: /* ALPHA_R_BSR */
- case ETIR_S_C_STC_LDA_GBL: /* ALPHA_R_LDA */
- case ETIR_S_C_STC_BOH_GBL: /* ALPHA_R_BOH */
- break;
-
- case ETIR_S_C_STO_IMM:
- if (PRIV (image_section)->reloc_count == 0)
- continue;
- /* This is not a relocation, but we nevertheless slurp the
- count argument. We'll use it to compute the addresses
- of the relocations. */
- slurped_length = ETIR_S_C_HEADER_SIZE + 4;
- break;
-
- default:
- continue;
- }
-
- vsd = vms_section_data (PRIV (image_section));
- memcpy (vsd->reloc_stream + vsd->reloc_offset, ptr, slurped_length);
- vsd->reloc_offset += slurped_length;
- if (vsd->reloc_offset > vsd->reloc_size)
- {
- (*_bfd_error_handler) (_("Reloc size error in section %s"),
- PRIV (image_section)->name);
- return -1;
- }
- }
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "_bfd_vms_slurp_relocs: result = 0\n");
-#endif
-
- return 0;
-}
-
-/* Decode relocs from the reloc buffer of the specified section
- and internalize them in the specified buffer. */
-
-int
-_bfd_vms_decode_relocs (bfd *abfd, arelent *relocs, asection *section,
- asymbol **symbols ATTRIBUTE_UNUSED)
-{
- int saved_cmd, saved_sym_offset, saved_sec_offset, saved_addend_offset;
- int cmd, sym_offset, sec_offset, address_offset, addend_offset;
- struct vms_section_data_struct *vsd = vms_section_data (section);
- bfd_reloc_code_real_type reloc_code;
- vms_symbol_entry *entry;
- bfd_vma vaddr = 0;
- unsigned char *begin = vsd->reloc_stream;
- unsigned char *end = vsd->reloc_stream + vsd->reloc_size;
- unsigned char *ptr, *arg_ptr;
- const char *name;
- int length;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "_bfd_vms_decode_relocs: %d bytes\n", vsd->reloc_size);
-#endif
-
- #define PUSH_CMD() \
- { \
- saved_cmd = cmd; \
- saved_sym_offset = sym_offset - length; \
- saved_sec_offset = sec_offset - length; \
- saved_addend_offset = addend_offset - length; \
- continue; \
- }
-
- #define POP_CMD() \
- { \
- cmd = saved_cmd; \
- saved_cmd = ETIR_S_C_MAXSTCCOD + 1; \
- sym_offset = saved_sym_offset; \
- sec_offset = saved_sec_offset; \
- addend_offset= saved_addend_offset; \
- }
-
- #define CMD_PUSHED (saved_cmd != ETIR_S_C_MAXSTCCOD + 1)
-
- #define NO_OFFSET -128
-
- saved_cmd = ETIR_S_C_MAXSTCCOD + 1;
- saved_sym_offset = NO_OFFSET;
- saved_sec_offset = NO_OFFSET;
- saved_addend_offset = NO_OFFSET;
-
- for (ptr = begin; ptr < end; ptr += length)
- {
- cmd = bfd_getl16 (ptr);
- length = bfd_getl16 (ptr + 2);
-
- arg_ptr = ptr + ETIR_S_C_HEADER_SIZE;
- sym_offset = NO_OFFSET;
- sec_offset = NO_OFFSET;
- address_offset = NO_OFFSET;
- addend_offset = NO_OFFSET;
-
- switch (cmd)
- {
- case ETIR_S_C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */
- /* ALPHA_R_REFQUAD und_section, step 1 */
- sym_offset = 0;
- PUSH_CMD ()
-
- case ETIR_S_C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */
- sec_offset = 0;
- addend_offset = 4;
- PUSH_CMD ()
-
- case ETIR_S_C_STA_LW: /* ALPHA_R_REFLONG abs_section, step 1 */
- /* ALPHA_R_REFLONG und_section, step 2 */
- if (CMD_PUSHED)
- {
- POP_CMD ()
- if (cmd != ETIR_S_C_STA_GBL)
- {
- (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
- cmd_name (cmd),
- cmd_name (ETIR_S_C_STA_LW));
- return 0;
- }
- cmd = ETIR_S_C_STA_LW;
- }
- addend_offset = 0;
- PUSH_CMD ()
-
- case ETIR_S_C_STA_QW: /* ALPHA_R_REFQUAD abs_section, step 1 */
- /* ALPHA_R_REFQUAD und_section, step 2 */
- if (CMD_PUSHED)
- {
- POP_CMD ()
- if (cmd != ETIR_S_C_STA_GBL)
- {
- (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
- cmd_name (cmd),
- cmd_name (ETIR_S_C_STA_QW));
- return 0;
- }
- cmd = ETIR_S_C_STA_QW;
- }
- addend_offset = 0;
- PUSH_CMD ()
-
- case ETIR_S_C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */
- /* ALPHA_R_REFLONG abs_section, step 2 */
- /* ALPHA_R_REFLONG others, step 2 */
- POP_CMD ()
- if (cmd != ETIR_S_C_OPR_ADD
- && cmd != ETIR_S_C_STA_LW
- && cmd != ETIR_S_C_STA_PQ)
- {
- (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
- cmd_name (cmd), cmd_name (ETIR_S_C_STO_LW));
- return 0;
- }
- reloc_code = BFD_RELOC_32;
- break;
-
- case ETIR_S_C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */
- /* ALPHA_R_REFQUAD abs_section, step 2 */
- POP_CMD ()
- if (cmd != ETIR_S_C_OPR_ADD && cmd != ETIR_S_C_STA_QW)
- {
- (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
- cmd_name (cmd), cmd_name (ETIR_S_C_STO_QW));
- return 0;
- }
- reloc_code = BFD_RELOC_64;
- break;
-
- case ETIR_S_C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */
- POP_CMD ()
- if (cmd != ETIR_S_C_STA_PQ)
- {
- (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
- cmd_name (cmd), cmd_name (ETIR_S_C_STO_OFF));
- return 0;
- }
- reloc_code = BFD_RELOC_64;
- break;
-
- case ETIR_S_C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */
- /* ALPHA_R_REFQUAD und_section, step 3 */
- POP_CMD ()
- if (cmd != ETIR_S_C_STA_LW && cmd != ETIR_S_C_STA_QW)
- {
- (*_bfd_error_handler) (_("Unknown reloc %s + %s"),
- cmd_name (cmd), cmd_name (ETIR_S_C_OPR_ADD));
- return 0;
- }
- cmd = ETIR_S_C_OPR_ADD;
- PUSH_CMD ()
-
- case ETIR_S_C_STO_CA: /* ALPHA_R_CODEADDR */
- reloc_code = BFD_RELOC_ALPHA_CODEADDR;
- sym_offset = 0;
- break;
-
- case ETIR_S_C_STO_GBL: /* ALPHA_R_REFQUAD und_section */
- reloc_code = BFD_RELOC_64;
- sym_offset = 0;
- break;
-
- case ETIR_S_C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */
- reloc_code = BFD_RELOC_32;
- sym_offset = 0;
- break;
-
- case ETIR_S_C_STC_LP_PSB: /* ALPHA_R_LINKAGE */
- reloc_code = BFD_RELOC_ALPHA_LINKAGE;
- sym_offset = 4;
- break;
-
- case ETIR_S_C_STC_NOP_GBL: /* ALPHA_R_NOP */
- reloc_code = BFD_RELOC_ALPHA_NOP;
- goto call_reloc;
-
- case ETIR_S_C_STC_BSR_GBL: /* ALPHA_R_BSR */
- reloc_code = BFD_RELOC_ALPHA_BSR;
- goto call_reloc;
-
- case ETIR_S_C_STC_LDA_GBL: /* ALPHA_R_LDA */
- reloc_code = BFD_RELOC_ALPHA_LDA;
- goto call_reloc;
-
- case ETIR_S_C_STC_BOH_GBL: /* ALPHA_R_BOH */
- reloc_code = BFD_RELOC_ALPHA_BOH;
- goto call_reloc;
-
- call_reloc:
- sym_offset = 32;
- address_offset = 8;
- addend_offset = 24;
- break;
-
- case ETIR_S_C_STO_IMM:
- vaddr += bfd_getl32 (arg_ptr);
- length = ETIR_S_C_HEADER_SIZE + 4;
- continue;
-
- default:
- continue;
- }
-
- relocs->howto = bfd_reloc_type_lookup (abfd, reloc_code);
-
- if (sym_offset > NO_OFFSET)
- {
- name = _bfd_vms_save_counted_string (arg_ptr + sym_offset);
- entry = (vms_symbol_entry *)
- bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
- if (entry == NULL)
- {
- (*_bfd_error_handler) (_("Unknown symbol %s in command %s"),
- name, cmd_name (cmd));
- relocs->sym_ptr_ptr = NULL;
- }
- else
- /* ??? This is a hack. We should point in 'symbols'. */
- relocs->sym_ptr_ptr = &entry->symbol;
- }
- else if (sec_offset > NO_OFFSET)
- relocs->sym_ptr_ptr
- = PRIV (sections)[bfd_getl32 (arg_ptr + sec_offset)]->symbol_ptr_ptr;
- else
- relocs->sym_ptr_ptr = NULL;
-
- if (address_offset > NO_OFFSET)
- relocs->address = bfd_getl64 (arg_ptr + address_offset);
- else
- relocs->address = vaddr;
-
- if (addend_offset > NO_OFFSET)
- relocs->addend = bfd_getl64 (arg_ptr + addend_offset);
- else
- relocs->addend = 0;
-
- vaddr += bfd_get_reloc_size (relocs->howto);
- relocs++;
- }
-
- #undef PUSH_CMD
- #undef POP_CMD
- #undef NO_OFFSET
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "_bfd_vms_decode_relocs: result = 0\n");
-#endif
-
- return 0;
-}
-
-/* Process LNK record
- Return 0 on success, -1 on error
-
- Not implemented yet. */
-
-int
-_bfd_vms_slurp_lnk (bfd * abfd ATTRIBUTE_UNUSED,
- int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "LNK\n");
-#endif
-
- return 0;
-}
-\f
-/* WRITE ETIR SECTION
-
- This is still under construction and therefore not documented. */
-
-static void start_etir_record (bfd *abfd, int sec_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 sec_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
-start_etir_record (bfd * abfd, int sec_index, uquad offset, bfd_boolean justoffset)
-{
- if (!justoffset)
- {
- /* One ETIR per section. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_ETIR, -1);
- _bfd_vms_output_push (abfd);
- }
-
- /* Push start offset. */
- _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) offset);
- _bfd_vms_output_flush (abfd);
-
- /* Start = pop (). */
- _bfd_vms_output_begin (abfd, ETIR_S_C_CTL_SETRB, -1);
- _bfd_vms_output_flush (abfd);
-}
-
-static void
-end_etir_record (bfd * abfd)
-{
- _bfd_vms_output_pop (abfd);
- _bfd_vms_output_end (abfd);
-}
-
-/* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual
- address VADDR in section specified by SEC_INDEX and NAME. */
-
-static void
-sto_imm (bfd *abfd, bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr,
- int sec_index, const char *name)
-{
- bfd_size_type size;
-
-#if VMS_DEBUG
- _bfd_vms_debug (8, "sto_imm %d bytes\n", ssize);
- _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr);
-#endif
-
- while (ssize > 0)
- {
- /* Try all the rest. */
- size = ssize;
-
- if (_bfd_vms_output_check (abfd, size) < 0)
- {
- /* Doesn't fit, split ! */
- end_etir_record (abfd);
-
- if (name [0] && name[1] == 'v' && !strcmp (name, ".vmsdebug"))
- start_another_etbt_record (abfd);
- else
- start_etir_record (abfd, sec_index, vaddr, FALSE);
-
- size = _bfd_vms_output_check (abfd, 0); /* get max size */
- if (size > ssize) /* more than what's left ? */
- size = ssize;
- }
-
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_IMM, -1);
- _bfd_vms_output_long (abfd, (unsigned long) (size));
- _bfd_vms_output_dump (abfd, cptr, size);
- _bfd_vms_output_flush (abfd);
-
-#if VMS_DEBUG
- _bfd_vms_debug (10, "dumped %d bytes\n", size);
- _bfd_hexdump (10, cptr, (int) size, (int) vaddr);
-#endif
-
- vaddr += size;
- cptr += size;
- ssize -= size;
- }
-}
-
-/* Start ETBT record for section #index at virtual addr offset. */
-
-static void
-start_first_etbt_record (bfd *abfd)
-{
- _bfd_vms_output_begin (abfd, EOBJ_S_C_ETBT, -1);
- _bfd_vms_output_push (abfd);
-
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1); /* push start offset */
- _bfd_vms_output_long (abfd, (unsigned long) 0);
- _bfd_vms_output_flush (abfd);
-
- _bfd_vms_output_begin (abfd, ETIR_S_C_CTL_DFLOC, -1); /* start = pop() */
- _bfd_vms_output_flush (abfd);
-}
-
-static void
-start_another_etbt_record (bfd *abfd)
-{
- _bfd_vms_output_begin (abfd, EOBJ_S_C_ETBT, -1);
- _bfd_vms_output_push (abfd);
-}
-
-static void
-etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen)
-{
- if (_bfd_vms_output_check (abfd, checklen) < 0)
- {
- end_etir_record (abfd);
- if (section->name[0] && section->name[1] == 'v'
- && !strcmp (section->name, ".vmsdebug"))
- start_another_etbt_record (abfd);
- else
- start_etir_record (abfd, section->index, vaddr, FALSE);
- }
-}
-
-/* Return whether RELOC must be deferred till the end. */
-
-static int
-defer_reloc_p (arelent *reloc)
-{
- switch (reloc->howto->type)
- {
- case ALPHA_R_NOP:
- case ALPHA_R_LDA:
- case ALPHA_R_BSR:
- case ALPHA_R_BOH:
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Write section contents for bfd abfd. */
-
-int
-_bfd_vms_write_tir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
-{
- asection *section;
-
-#if VMS_DEBUG
- _bfd_vms_debug (2, "vms_write_tir (%p, %d)\n", abfd, objtype);
-#endif
-
- _bfd_vms_output_alignment (abfd, 4);
-
- PRIV (vms_linkage_index) = 1;
-
- for (section = abfd->sections; section; section = section->next)
- {
-#if VMS_DEBUG
- _bfd_vms_debug (4, "writing %d. section '%s' (%d bytes)\n",
- section->index, section->name,
- (int) (section->size));
-#endif
-
- if (!(section->flags & SEC_HAS_CONTENTS)
- || bfd_is_com_section (section))
- continue;
-
- if (!section->contents)
- {
- bfd_set_error (bfd_error_no_contents);
- return -1;
- }
-
- if (section->name[0]
- && section->name[1] == 'v'
- && !strcmp (section->name, ".vmsdebug"))
- start_first_etbt_record (abfd);
- else
- start_etir_record (abfd, section->index, 0, FALSE);
-
- if (section->flags & SEC_RELOC)
- {
- bfd_vma curr_addr = 0;
- unsigned char *curr_data = section->contents;
- bfd_size_type size;
- int pass2_needed = 0;
- int pass2_in_progress = 0;
- unsigned int irel;
-
- if (section->reloc_count <= 0)
- (*_bfd_error_handler)
- (_("SEC_RELOC with no relocs in section %s"), section->name);
-
-#if VMS_DEBUG
- else
- {
- int i = section->reloc_count;
- arelent **rptr = section->orelocation;
- _bfd_vms_debug (4, "%d relocations:\n", i);
- while (i-- > 0)
- {
- _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, "
- "addr %08lx, off %08lx, len %d: %s\n",
- (*(*rptr)->sym_ptr_ptr)->name,
- (*(*rptr)->sym_ptr_ptr)->section->name,
- (long) (*(*rptr)->sym_ptr_ptr)->value,
- (*rptr)->address, (*rptr)->addend,
- bfd_get_reloc_size ((*rptr)->howto),
- ( *rptr)->howto->name);
- rptr++;
- }
- }
-#endif
-
- new_pass:
- for (irel = 0; irel < section->reloc_count; irel++)
- {
- struct evax_private_udata_struct *udata;
- arelent *rptr = section->orelocation [irel];
- bfd_vma addr = rptr->address;
- asymbol *sym = *rptr->sym_ptr_ptr;
- asection *sec = sym->section;
- int defer = defer_reloc_p (rptr);
- unsigned int slen;
- char *hash;
-
- if (pass2_in_progress)
- {
- /* Non-deferred relocs have already been output. */
- if (!defer)
- continue;
- }
- else
- {
- /* Deferred relocs must be output at the very end. */
- if (defer)
- {
- pass2_needed = 1;
- continue;
- }
-
- /* Regular relocs are intertwined with binary data. */
- if (curr_addr > addr)
- (*_bfd_error_handler) (_("Size error in section %s"),
- section->name);
- size = addr - curr_addr;
- sto_imm (abfd, size, curr_data, curr_addr,
- section->index, section->name);
- curr_data += size;
- curr_addr += size;
- }
-
- size = bfd_get_reloc_size (rptr->howto);
-
- switch (rptr->howto->type)
- {
- case ALPHA_R_IGNORE:
- break;
-
- case ALPHA_R_REFLONG:
- if (bfd_is_und_section (sym->section))
- {
- bfd_vma addend = rptr->addend;
- slen = strlen ((char *) sym->name);
- hash = _bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ);
- etir_output_check (abfd, section, curr_addr, slen);
- if (addend)
- {
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_GBL, -1);
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1);
- _bfd_vms_output_long (abfd, (unsigned long) addend);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_OPR_ADD, -1);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1);
- _bfd_vms_output_flush (abfd);
- }
- else
- {
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_GBL_LW, -1);
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- }
- }
- else if (bfd_is_abs_section (sym->section))
- {
- etir_output_check (abfd, section, curr_addr, 16);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1);
- _bfd_vms_output_long (abfd, (unsigned long) sym->value);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1);
- _bfd_vms_output_flush (abfd);
- }
- else
- {
- etir_output_check (abfd, section, curr_addr, 32);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1);
- _bfd_vms_output_long (abfd, (unsigned long) sec->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->addend
- + (uquad) sym->value);
- _bfd_vms_output_flush (abfd);
- /* ??? Table B-8 of the OpenVMS Linker Utilily Manual
- says that we should have a ETIR_S_C_STO_OFF here.
- But the relocation would not be BFD_RELOC_32 then.
- This case is very likely unreachable. */
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1);
- _bfd_vms_output_flush (abfd);
- }
- break;
-
- case ALPHA_R_REFQUAD:
- if (bfd_is_und_section (sym->section))
- {
- bfd_vma addend = rptr->addend;
- slen = strlen ((char *) sym->name);
- hash = _bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ);
- etir_output_check (abfd, section, curr_addr, slen);
- if (addend)
- {
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_GBL, -1);
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_QW, -1);
- _bfd_vms_output_quad (abfd, (uquad) addend);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_OPR_ADD, -1);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_QW, -1);
- _bfd_vms_output_flush (abfd);
- }
- else
- {
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_GBL, -1);
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- }
- }
- else if (bfd_is_abs_section (sym->section))
- {
- etir_output_check (abfd, section, curr_addr, 16);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_QW, -1);
- _bfd_vms_output_quad (abfd, (uquad) sym->value);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_QW, -1);
- _bfd_vms_output_flush (abfd);
- }
- else
- {
- etir_output_check (abfd, section, curr_addr, 32);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1);
- _bfd_vms_output_long (abfd, (unsigned long) sec->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->addend
- + (uquad) sym->value);
- _bfd_vms_output_flush (abfd);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_OFF, -1);
- _bfd_vms_output_flush (abfd);
- }
- break;
-
- case ALPHA_R_HINT:
- sto_imm (abfd, size, curr_data, curr_addr,
- section->index, section->name);
- break;
-
- case ALPHA_R_LINKAGE:
- etir_output_check (abfd, section, curr_addr, 64);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STC_LP_PSB, -1);
- _bfd_vms_output_long
- (abfd, (unsigned long) PRIV (vms_linkage_index));
- PRIV (vms_linkage_index) += 2;
- hash = _bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ);
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_byte (abfd, 0);
- _bfd_vms_output_flush (abfd);
- break;
-
- case ALPHA_R_CODEADDR:
- slen = strlen ((char *) sym->name);
- hash = _bfd_vms_length_hash_symbol
- (abfd, sym->name, EOBJ_S_C_SYMSIZ);
- etir_output_check (abfd, section, curr_addr, slen);
- _bfd_vms_output_begin (abfd, ETIR_S_C_STO_CA, -1);
- _bfd_vms_output_counted (abfd, hash);
- _bfd_vms_output_flush (abfd);
- break;
-
- case ALPHA_R_NOP:
- udata
- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
- etir_output_check (abfd, section, curr_addr,
- 32 + 1 + strlen (udata->origname));
- _bfd_vms_output_begin (abfd, ETIR_S_C_STC_NOP_GBL, -1);
- _bfd_vms_output_long (abfd, (unsigned long) udata->lkindex);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->enbsym->section->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->address);
- _bfd_vms_output_long (abfd, (unsigned long) 0x47ff041f);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->enbsym->section->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->addend);
- _bfd_vms_output_counted
- (abfd, _bfd_vms_length_hash_symbol
- (abfd, udata->origname, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_flush (abfd);
- break;
-
- case ALPHA_R_BSR:
- (*_bfd_error_handler) (_("Spurious ALPHA_R_BSR reloc"));
- break;
-
- case ALPHA_R_LDA:
- udata
- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
- etir_output_check (abfd, section, curr_addr,
- 32 + 1 + strlen (udata->origname));
- _bfd_vms_output_begin (abfd, ETIR_S_C_STC_LDA_GBL, -1);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->lkindex + 1);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->enbsym->section->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->address);
- _bfd_vms_output_long (abfd, (unsigned long) 0x237B0000);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->bsym->section->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->addend);
- _bfd_vms_output_counted
- (abfd, _bfd_vms_length_hash_symbol
- (abfd, udata->origname, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_flush (abfd);
- break;
-
- case ALPHA_R_BOH:
- udata
- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
- etir_output_check (abfd, section, curr_addr,
- 32 + 1 + strlen (udata->origname));
- _bfd_vms_output_begin (abfd, ETIR_S_C_STC_BOH_GBL, -1);
- _bfd_vms_output_long (abfd, (unsigned long) udata->lkindex);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->enbsym->section->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->address);
- _bfd_vms_output_long (abfd, (unsigned long) 0xD3400000);
- _bfd_vms_output_long
- (abfd, (unsigned long) udata->enbsym->section->index);
- _bfd_vms_output_quad (abfd, (uquad) rptr->addend);
- _bfd_vms_output_counted
- (abfd, _bfd_vms_length_hash_symbol
- (abfd, udata->origname, EOBJ_S_C_SYMSIZ));
- _bfd_vms_output_flush (abfd);
- break;
-
- default:
- (*_bfd_error_handler) (_("Unhandled relocation %s"),
- rptr->howto->name);
- break;
- }
-
- curr_data += size;
- curr_addr += size;
- } /* End of relocs loop. */
-
- if (!pass2_in_progress)
- {
- /* Output rest of section. */
- if (curr_addr > section->size)
- (*_bfd_error_handler) (_("Size error in section %s"),
- section->name);
- size = section->size - curr_addr;
- sto_imm (abfd, size, curr_data, curr_addr,
- section->index, section->name);
- curr_data += size;
- curr_addr += size;
-
- if (pass2_needed)
- {
- pass2_in_progress = 1;
- goto new_pass;
- }
- }
- }
-
- else /* (section->flags & SEC_RELOC) */
- sto_imm (abfd, section->size, section->contents, 0,
- section->index, section->name);
-
- end_etir_record (abfd);
- }
-
- _bfd_vms_output_alignment (abfd, 2);
- return 0;
-}
+++ /dev/null
-/* vms.c -- BFD back-end for VAX (openVMS/VAX) and
- EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-
- Main file.
-
- Written by Klaus K"ampf (kkaempf@rmi.de)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
-
-#ifdef VMS
-#include <rms.h>
-#include <unixlib.h>
-#include <starlet.h>
-#define RME$C_SETRFM 0x00000001
-#include <unistd.h>
-#endif
-
-#include "sysdep.h"
-#include "bfd.h"
-#include "bfdlink.h"
-#include "libbfd.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 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_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 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 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 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);
-
-#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_link_hash_symbol_type \
- _bfd_generic_copy_link_hash_symbol_type
-#define vms_bfd_is_group_section bfd_generic_is_group_section
-#define vms_bfd_discard_group bfd_generic_discard_group
-#define vms_section_already_linked _bfd_generic_section_already_linked
-#define vms_bfd_define_common_symbol bfd_generic_define_common_symbol
-#define vms_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
-#define vms_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab
-
-#define vms_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
-#define vms_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
-#define vms_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
-#define vms_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
-#define vms_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
-#define vms_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
-#define vms_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
-#define vms_read_minisymbols _bfd_generic_read_minisymbols
-#define vms_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
-#define vms_get_lineno _bfd_nosymbols_get_lineno
-#define vms_find_inliner_info _bfd_nosymbols_find_inliner_info
-#define vms_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
-\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;
-
-/* Initialize private data */
-static bfd_boolean
-vms_initialize (bfd * abfd)
-{
- bfd_size_type amt;
-
- bfd_set_start_address (abfd, (bfd_vma) -1);
-
- amt = sizeof (struct vms_private_data_struct);
- abfd->tdata.any = bfd_zalloc (abfd, amt);
- if (abfd->tdata.any == NULL)
- return FALSE;
-
- if (bfd_get_flavour (abfd) == bfd_target_ovax_flavour)
- PRIV (is_vax) = TRUE;
-
- PRIV (file_format) = FF_UNKNOWN;
-
- amt = sizeof (struct stack_struct) * STACKSIZE;
- PRIV (stack) = bfd_alloc (abfd, amt);
- if (PRIV (stack) == NULL)
- goto error_ret1;
-
- amt = sizeof (struct bfd_hash_table);
- PRIV (vms_symbol_table) = bfd_alloc (abfd, amt);
- if (PRIV (vms_symbol_table) == NULL)
- goto error_ret1;
-
- if (!bfd_hash_table_init (PRIV (vms_symbol_table), _bfd_vms_hash_newfunc,
- sizeof (vms_symbol_entry)))
- goto error_ret1;
-
- amt = MAX_OUTREC_SIZE;
- PRIV (output_buf) = bfd_alloc (abfd, amt);
- if (PRIV (output_buf) == NULL)
- goto error_ret2;
-
- PRIV (length_pos) = 2;
-
- return TRUE;
-
- error_ret2:
- bfd_hash_table_free (PRIV (vms_symbol_table));
- error_ret1:
- bfd_release (abfd, abfd->tdata.any);
- abfd->tdata.any = NULL;
- return FALSE;
-}
-
-struct pair
-{
- unsigned int section_count;
- asection **sections;
-};
-
-/* Fill symbol->section with section pointer.
-
- symbol->section is filled with the section index for defined symbols
- during reading the GSD/EGSD section. But we need the pointer to the
- bfd section later.
-
- It has the correct value for referenced (undefined section) symbols.
-
- Called from bfd_hash_traverse in vms_fixup_sections. */
-
-static bfd_boolean
-fill_section_ptr (struct bfd_hash_entry *entry, void *sections)
-{
- asymbol *sym = ((vms_symbol_entry *)entry)->symbol;
- struct pair *data = (struct pair *)sections;
- unsigned long sec = (unsigned long)sym->section;
-
- vms_debug2 ((6, "fill_section_ptr: sym %p, sec %lu\n", sym, sec));
-
- if (sec < data->section_count)
- {
- sym->section = data->sections[sec];
-
- if (strcmp (sym->name, sym->section->name) == 0)
- sym->flags |= BSF_SECTION_SYM;
- }
- else if (sec == (unsigned long)-1)
- sym->section = &bfd_und_section;
-
- return TRUE;
-}
-
-/* Fixup section pointers in symbols. */
-static bfd_boolean
-vms_fixup_sections (bfd * abfd)
-{
- struct pair data;
-
- if (PRIV (fixup_done))
- return TRUE;
-
- data.section_count = PRIV (section_count);
- data.sections = PRIV (sections);
- bfd_hash_traverse (PRIV (vms_symbol_table), fill_section_ptr, &data);
-
- PRIV (fixup_done) = TRUE;
- return TRUE;
-}
-
-/* Slurp an ordered set of VMS object records. */
-int
-_bfd_vms_slurp_object_records (bfd * abfd)
-{
- int err, new_type, type = -1;
-
- do
- {
- vms_debug2 ((7, "reading at %08lx\n", bfd_tell (abfd)));
-
- new_type = _bfd_vms_get_object_record (abfd);
- if (new_type < 0)
- {
- vms_debug2 ((2, "next_record failed\n"));
- return -1;
- }
-
- if (type == EOBJ_S_C_EGSD && new_type != EOBJ_S_C_EGSD)
- {
- if (! vms_fixup_sections (abfd))
- {
- vms_debug2 ((2, "vms_fixup_sections failed\n"));
- return -1;
- }
- }
-
- type = new_type;
-
- switch (type)
- {
- case OBJ_S_C_HDR:
- case EOBJ_S_C_EMH:
- err = _bfd_vms_slurp_hdr (abfd, type);
- break;
- case OBJ_S_C_EOM:
- case OBJ_S_C_EOMW:
- case EOBJ_S_C_EEOM:
- err = _bfd_vms_slurp_eom (abfd, type);
- break;
- case OBJ_S_C_GSD:
- case EOBJ_S_C_EGSD:
- err = _bfd_vms_slurp_gsd (abfd, type);
- break;
- case OBJ_S_C_TIR:
- case EOBJ_S_C_ETIR:
- err = _bfd_vms_slurp_tir (abfd, type);
- break;
- case OBJ_S_C_DBG:
- case EOBJ_S_C_EDBG:
- err = _bfd_vms_slurp_dbg (abfd, type);
- PRIV (dst_ptr_end) = PRIV (image_ptr);
- break;
- case OBJ_S_C_TBT:
- case EOBJ_S_C_ETBT:
- err = _bfd_vms_slurp_tbt (abfd, type);
- PRIV (dst_ptr_end) = PRIV (image_ptr);
- break;
- case OBJ_S_C_LNK:
- err = _bfd_vms_slurp_lnk (abfd, type);
- break;
- default:
- err = -1;
- }
- if (err != 0)
- {
- vms_debug2 ((2, "slurp type %d failed with %d\n", type, err));
- return err;
- }
- }
- while (type != EOBJ_S_C_EEOM && type != OBJ_S_C_EOM && type != OBJ_S_C_EOMW);
-
- return 0;
-}
-
-/* Slurp a VMS module and return an error status. */
-
-static int
-vms_slurp_module (bfd *abfd)
-{
- int type, err;
-
- if (PRIV (is_vax))
- type = PRIV (vms_rec)[0];
- else
- type = bfd_getl16 (PRIV (vms_rec));
-
- err = _bfd_vms_slurp_hdr (abfd, type);
- if (err != 0)
- {
- bfd_set_error (bfd_error_wrong_format);
- return err;
- }
-
- return _bfd_vms_slurp_object_records (abfd);
-}
-
-/* Slurp a VMS image and return an error status. */
-
-static int
-vms_slurp_image (bfd *abfd)
-{
- unsigned int isd_offset, ihs_offset;
- int err;
-
- err = _bfd_vms_slurp_ihd (abfd, &isd_offset, &ihs_offset);
- if (err != 0)
- {
- bfd_set_error (bfd_error_wrong_format);
- return err;
- }
-
- err = _bfd_vms_slurp_isd (abfd, isd_offset);
- if (err != 0)
- {
- bfd_set_error (bfd_error_wrong_format);
- return err;
- }
-
- return _bfd_vms_slurp_ihs (abfd, ihs_offset);
-}
-
-/* Check the format for a file being read.
- Return a (bfd_target *) if it's an object file or zero if not. */
-
-static const struct bfd_target *
-vms_object_p (bfd *abfd)
-{
- const struct bfd_target *target_vector;
- const bfd_arch_info_type *arch;
- PTR tdata_save = abfd->tdata.any;
- bfd_vma saddr_save = bfd_get_start_address (abfd);
- int err = 0;
-
- vms_debug2 ((1, "vms_object_p(%p)\n", abfd));
-
- 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))
- {
- vms_debug2 ((2, "vms_fixup_sections failed\n"));
- goto err_wrong_format;
- }
-
- target_vector = &vms_vax_vec;
- arch = bfd_scan_arch ("vax");
-
- vms_debug2 ((2, "arch is vax\n"));
- }
- else
- {
- /* Set arch_info to alpha. */
- target_vector = &vms_alpha_vec;
- arch = bfd_scan_arch ("alpha");
- vms_debug2 ((2, "arch is alpha\n"));
- }
-
- 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);
- abfd->tdata.any = tdata_save;
- bfd_set_start_address (abfd, saddr_save);
- return NULL;
-}
-
-/* Set the format of a file being written. */
-
-static bfd_boolean
-vms_mkobject (bfd * abfd)
-{
- const bfd_arch_info_type *arch;
-
- vms_debug2 ((1, "vms_mkobject (%p)\n", abfd));
-
- if (!vms_initialize (abfd))
- return FALSE;
-
- if (PRIV (is_vax))
- arch = bfd_scan_arch ("vax");
- else
- arch = bfd_scan_arch ("alpha");
-
- if (arch == 0)
- {
- bfd_set_error(bfd_error_wrong_format);
- return FALSE;
- }
-
- abfd->arch_info = arch;
- return TRUE;
-}
-
-/* Write cached information into a file being written, at bfd_close. */
-
-static bfd_boolean
-vms_write_object_contents (bfd * abfd)
-{
- vms_debug2 ((1, "vms_write_object_contents (%p)\n", abfd));
-
- if (abfd->section_count > 0) /* we have sections */
- {
- if (PRIV (is_vax))
- {
- if (_bfd_vms_write_hdr (abfd, OBJ_S_C_HDR) != 0)
- return FALSE;
- if (_bfd_vms_write_gsd (abfd, OBJ_S_C_GSD) != 0)
- return FALSE;
- if (_bfd_vms_write_tir (abfd, OBJ_S_C_TIR) != 0)
- return FALSE;
- if (_bfd_vms_write_tbt (abfd, OBJ_S_C_TBT) != 0)
- return FALSE;
- if (_bfd_vms_write_dbg (abfd, OBJ_S_C_DBG) != 0)
- return FALSE;
- if (abfd->section_count > 255)
- {
- if (_bfd_vms_write_eom (abfd, OBJ_S_C_EOMW) != 0)
- return FALSE;
- }
- else
- {
- if (_bfd_vms_write_eom (abfd, OBJ_S_C_EOM) != 0)
- return FALSE;
- }
- }
- else
- {
- if (_bfd_vms_write_hdr (abfd, EOBJ_S_C_EMH) != 0)
- return FALSE;
- if (_bfd_vms_write_gsd (abfd, EOBJ_S_C_EGSD) != 0)
- return FALSE;
- if (_bfd_vms_write_tir (abfd, EOBJ_S_C_ETIR) != 0)
- return FALSE;
- if (_bfd_vms_write_tbt (abfd, EOBJ_S_C_ETBT) != 0)
- return FALSE;
- if (_bfd_vms_write_dbg (abfd, EOBJ_S_C_EDBG) != 0)
- return FALSE;
- if (_bfd_vms_write_eom (abfd, EOBJ_S_C_EEOM) != 0)
- return FALSE;
- }
- }
- 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
-vms_close_and_cleanup (bfd * abfd)
-{
- vms_debug2 ((1, "vms_close_and_cleanup (%p)\n", abfd));
-
- if (abfd == NULL || abfd->tdata.any == NULL)
- return TRUE;
-
- if (PRIV (vms_buf) != NULL)
- free (PRIV (vms_buf));
-
- if (PRIV (sections) != NULL)
- free (PRIV (sections));
-
- 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;
-}
-
-/* Called when a new section is created. */
-
-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_debug2 ((1, "vms_new_section_hook (%p, [%d]%s), count %d\n",
- abfd, section->index, section->name, section_count));
-
- bfd_set_section_alignment (abfd, section, 0);
-
- if (section_count > PRIV (section_count))
- {
- amt = section_count;
- amt *= sizeof (asection *);
- PRIV (sections) = bfd_realloc_or_free (PRIV (sections), amt);
- if (PRIV (sections) == NULL)
- return FALSE;
- PRIV (section_count) = section_count;
- }
-
- vms_debug2 ((6, "section_count: %d\n", PRIV (section_count)));
-
- PRIV (sections)[section->index] = section;
-
- vms_debug2 ((7, "%d: %s\n", section->index, section->name));
-
- 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);
-}
-
-/* Read the contents of a section.
- buf points to a buffer of buf_size bytes to be filled with
- section data (starting at offset into section) */
-
-static bfd_boolean
-vms_get_section_contents (bfd * abfd ATTRIBUTE_UNUSED,
- asection *section ATTRIBUTE_UNUSED,
- void * buf ATTRIBUTE_UNUSED,
- file_ptr offset ATTRIBUTE_UNUSED,
- bfd_size_type buf_size ATTRIBUTE_UNUSED)
-{
- bfd_size_type size = section->size;
-
- vms_debug2 ((1, "vms_get_section_contents (%p, %s, %p, off %ld, size %d)\n",
- abfd, section->name, buf, offset, (int)buf_size));
-
- 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;
-}
-
-/* Part 4.5, symbols. */
-
-/* Return the number of bytes required to store a vector of pointers
- to asymbols for all the symbols in the BFD abfd, including a
- terminal NULL pointer. If there are no symbols in the BFD,
- then return 0. If an error occurs, return -1. */
-
-static long
-vms_get_symtab_upper_bound (bfd * abfd)
-{
- vms_debug2 ((1, "vms_get_symtab_upper_bound (%p), %d symbols\n",
- abfd, PRIV (gsd_sym_count)));
-
- return (PRIV (gsd_sym_count) + 1) * sizeof (asymbol *);
-}
-
-/* Copy symbols from hash table to symbol vector
-
- called from bfd_hash_traverse in vms_canonicalize_symtab
- init counter to 0 if entry == 0. */
-
-static bfd_boolean
-copy_symbols (struct bfd_hash_entry *entry, void * arg)
-{
- bfd * abfd = (bfd *) arg;
-
- if (entry == NULL) /* Init counter. */
- PRIV (symnum) = 0;
- else /* Fill vector, inc counter. */
- PRIV (symcache)[PRIV (symnum)++] = ((vms_symbol_entry *)entry)->symbol;
-
- return TRUE;
-}
-
-/* Read the symbols from the BFD abfd, and fills in the vector
- location with pointers to the symbols and a trailing NULL.
-
- Return number of symbols read. */
-
-static long
-vms_canonicalize_symtab (bfd * abfd, asymbol **symbols)
-{
- vms_debug2 ((1, "vms_canonicalize_symtab (%p, <ret>)\n", abfd));
-
- /* Init counter. */
- copy_symbols (NULL, abfd);
-
- /* Traverse table and fill symbols vector. */
- PRIV (symcache) = symbols;
- bfd_hash_traverse (PRIV (vms_symbol_table), copy_symbols, abfd);
-
- symbols[PRIV (gsd_sym_count)] = NULL;
-
- return PRIV (gsd_sym_count);
-}
-
-/* Print symbol to file according to how. how is one of
- bfd_print_symbol_name just print the name
- bfd_print_symbol_more print more (???)
- bfd_print_symbol_all print all we know, which is not much right now :-). */
-
-static void
-vms_print_symbol (bfd * abfd,
- void * file,
- asymbol *symbol,
- bfd_print_symbol_type how)
-{
- vms_debug2 ((1, "vms_print_symbol (%p, %p, %p, %d)\n",
- abfd, file, symbol, how));
-
- switch (how)
- {
- case bfd_print_symbol_name:
- case bfd_print_symbol_more:
- fprintf ((FILE *)file," %s", symbol->name);
- break;
-
- case bfd_print_symbol_all:
- {
- const char *section_name = symbol->section->name;
-
- bfd_print_symbol_vandf (abfd, file, symbol);
-
- fprintf ((FILE *) file," %-8s %s", section_name, symbol->name);
- }
- break;
- }
-}
-
-/* Return information about symbol in ret.
-
- fill type, value and name
- type:
- A absolute
- B bss segment symbol
- C common symbol
- D data segment symbol
- f filename
- t a static function symbol
- T text segment symbol
- U undefined
- - debug. */
-
-static void
-vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED,
- asymbol *symbol,
- symbol_info *ret)
-{
- asection *sec;
-
- vms_debug2 ((1, "vms_get_symbol_info (%p, %p, %p)\n", abfd, symbol, ret));
-
- sec = symbol->section;
-
- if (ret == NULL)
- return;
-
- if (sec == 0)
- ret->type = 'U';
- else if (bfd_is_com_section (sec))
- ret->type = 'C';
- else if (bfd_is_abs_section (sec))
- ret->type = 'A';
- else if (bfd_is_und_section (sec))
- ret->type = 'U';
- else if (bfd_is_ind_section (sec))
- ret->type = 'I';
- else if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
- ret->type = 'T';
- else if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
- ret->type = 'D';
- else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
- ret->type = 'B';
- else
- ret->type = '-';
-
- if (ret->type != 'U')
- ret->value = symbol->value + symbol->section->vma;
- else
- ret->value = 0;
- ret->name = symbol->name;
-}
-
-/* Return TRUE if the given symbol sym in the BFD abfd is
- a compiler generated local label, else return FALSE. */
-
-static bfd_boolean
-vms_bfd_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
- const char *name)
-{
- vms_debug2 ((1, "vms_bfd_is_local_label_name (%p, %s)\n", abfd, name));
- return name[0] == '$';
-}
-
-/* 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. */
-
-static bfd_boolean
-vms_find_nearest_line (bfd * abfd ATTRIBUTE_UNUSED,
- asection *section ATTRIBUTE_UNUSED,
- asymbol **symbols ATTRIBUTE_UNUSED,
- bfd_vma offset ATTRIBUTE_UNUSED,
- const char **file ATTRIBUTE_UNUSED,
- const char **func ATTRIBUTE_UNUSED,
- unsigned int *line ATTRIBUTE_UNUSED)
-{
- vms_debug2 ((1, "vms_find_nearest_line (%p, %s, %p, %ld, ...)\n",
- abfd, section->name, symbols, (long int)offset));
- return _bfd_vms_find_nearest_dst_line (abfd, section, symbols, offset, file, func, line);
-}
-
-/* Part 4.6, relocations. */
-
-/* Allocate the reloc buffer for the specified section. */
-
-static void
-alloc_reloc_stream (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
- void *alloc_error)
-{
- unsigned char *ptr;
-
- /* If there were no relocations, there is nothing to do. */
- if (section->reloc_count == 0)
- return;
-
- ptr = bfd_malloc (vms_section_data (section)->reloc_size);
- if (ptr == NULL)
- {
- *(bfd_boolean *)alloc_error = TRUE;
- return;
- }
-
- vms_section_data (section)->reloc_stream = ptr;
-}
-
-/* Read in the relocs for the specified section and internalize them.
-
- The implementation is loosely based on the SOM code and made up
- of 3 distinct phases:
-
- 1. When the VMS object is opened and parsed, the number and the size
- of the relocations are computed for all sections. This makes it
- possible to know upfront both which sections have no relocs and
- the size of the reloc buffers for the other sections, at virtually
- no cost for consumers that don't care about relocs at all.
-
- 2. When vms_slurp_reloc_table is invoked for the first time on a section
- with relocs, the object is traversed and all the reloc information
- is saved in per-section reloc buffers. It would be very inefficient
- to scan the whole file on each invocation, so we slurp for all the
- sections at once.
-
- 3. On subsequent invocations of vms_slurp_reloc_table, the relocs for the
- specified section are fetched from the buffer, decoded and internalized.
- The buffer is then freed since the internalized relocs are attached to
- the section, turning additional invocations of vms_slurp_reloc_table
- on the same section into no-ops.
-
- Since VMS objects have very few sections, it could be profitable to merge
- phase #2 and phase #3, i.e. to decode and internalize the relocs for all
- the sections at once. The current implementation is more elegant. */
-
-static bfd_boolean
-vms_slurp_reloc_table (bfd *abfd, asection *section, asymbol **symbols)
-{
- arelent *internal_relocs;
- bfd_size_type amt;
- int err;
-
- /* If there were no relocations, there is nothing to do. */
- if (section->reloc_count == 0)
- return TRUE;
-
- /* Return saved information about the relocations if it is available. */
- if (section->relocation != NULL)
- return TRUE;
-
- /* If the relocation stream has not been slurped, do it now. */
- if (vms_section_data (section)->reloc_stream == NULL)
- {
- bfd_boolean alloc_error = FALSE;
- int type;
-
- /* Size the reloc buffer for each section. */
- bfd_map_over_sections (abfd, alloc_reloc_stream, &alloc_error);
- if (alloc_error)
- return FALSE;
-
- if (bfd_seek (abfd, 0, SEEK_SET) != 0)
- return FALSE;
-
- /* Reset section pointer. */
- PRIV (image_section) = NULL;
-
- do
- {
- type = _bfd_vms_get_object_record (abfd);
- if (type != EOBJ_S_C_ETIR
- && type != EOBJ_S_C_EDBG
- && type != EOBJ_S_C_ETBT)
- continue;
- err = _bfd_vms_slurp_relocs (abfd);
- if (err != 0)
- {
- vms_debug2 ((2, "slurp relocs failed with %d\n", err));
- 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)
- {
- vms_debug2 ((2, "decode relocs failed with %d\n", err));
- return FALSE;
- }
-
- /* We're done with the external relocations. Free them. */
- free (vms_section_data (section)->reloc_stream);
- vms_section_data (section)->reloc_stream = NULL;
-
- /* Save our results and return success. */
- section->relocation = internal_relocs;
- return TRUE;
-}
-
-/* Return the number of bytes required to store the relocation
- information associated with the given section. */
-
-static long
-vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
-{
- return (section->reloc_count + 1) * sizeof (arelent *);
-}
-
-/* Convert relocations from VMS (external) form into BFD internal
- form. Return the number of relocations. */
-
-static long
-vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr,
- asymbol **symbols)
-{
- arelent *tblptr;
- int count;
-
- if (! vms_slurp_reloc_table (abfd, section, symbols))
- return -1;
-
- count = section->reloc_count;
- tblptr = section->relocation;
-
- while (count--)
- *relptr++ = tblptr++;
-
- *relptr = (arelent *) NULL;
- return section->reloc_count;
-}
-\f
-/* This is just copied from ecoff-alpha, needs to be fixed probably. */
-
-/* How to process the various reloc types. */
-
-static bfd_reloc_status_type
-reloc_nil (bfd * abfd ATTRIBUTE_UNUSED,
- arelent *reloc ATTRIBUTE_UNUSED,
- asymbol *sym ATTRIBUTE_UNUSED,
- void * data ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
- bfd *output_bfd ATTRIBUTE_UNUSED,
- char **error_message ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- vms_debug (1, "reloc_nil (abfd %p, output_bfd %p)\n", abfd, output_bfd);
- vms_debug (2, "In section %s, symbol %s\n",
- sec->name, sym->name);
- vms_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n",
- reloc->sym_ptr_ptr[0]->name,
- (unsigned long)reloc->address,
- (unsigned long)reloc->addend, reloc->howto->name);
- vms_debug (2, "data at %p\n", data);
- /* _bfd_hexdump (2, data, bfd_get_reloc_size (reloc->howto), 0); */
-#endif
-
- return bfd_reloc_ok;
-}
-
-/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
- from smaller values. Start with zero, widen, *then* decrement. */
-#define MINUS_ONE (((bfd_vma)0) - 1)
-
-static reloc_howto_type alpha_howto_table[] =
-{
- HOWTO (ALPHA_R_IGNORE, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 8, /* Bitsize. */
- TRUE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "IGNORE", /* Name. */
- TRUE, /* Partial_inplace. */
- 0, /* Source mask */
- 0, /* Dest mask. */
- TRUE), /* PC rel offset. */
-
- /* A 64 bit reference to a symbol. */
- HOWTO (ALPHA_R_REFQUAD, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "REFQUAD", /* Name. */
- TRUE, /* Partial_inplace. */
- MINUS_ONE, /* Source mask. */
- MINUS_ONE, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* A 21 bit branch. The native assembler generates these for
- branches within the text segment, and also fills in the PC
- relative offset in the instruction. */
- HOWTO (ALPHA_R_BRADDR, /* Type. */
- 2, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 21, /* Bitsize. */
- TRUE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "BRADDR", /* Name. */
- TRUE, /* Partial_inplace. */
- 0x1fffff, /* Source mask. */
- 0x1fffff, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* A hint for a jump to a register. */
- HOWTO (ALPHA_R_HINT, /* Type. */
- 2, /* Rightshift. */
- 1, /* Size (0 = byte, 1 = short, 2 = long). */
- 14, /* Bitsize. */
- TRUE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "HINT", /* Name. */
- TRUE, /* Partial_inplace. */
- 0x3fff, /* Source mask. */
- 0x3fff, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* 16 bit PC relative offset. */
- HOWTO (ALPHA_R_SREL16, /* Type. */
- 0, /* Rightshift. */
- 1, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- TRUE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "SREL16", /* Name. */
- TRUE, /* Partial_inplace. */
- 0xffff, /* Source mask. */
- 0xffff, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* 32 bit PC relative offset. */
- HOWTO (ALPHA_R_SREL32, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- TRUE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "SREL32", /* Name. */
- TRUE, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* A 64 bit PC relative offset. */
- HOWTO (ALPHA_R_SREL64, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- TRUE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "SREL64", /* Name. */
- TRUE, /* Partial_inplace. */
- MINUS_ONE, /* Source mask. */
- MINUS_ONE, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* Push a value on the reloc evaluation stack. */
- HOWTO (ALPHA_R_OP_PUSH, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_PUSH", /* Name. */
- FALSE, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* Store the value from the stack at the given address. Store it in
- a bitfield of size r_size starting at bit position r_offset. */
- HOWTO (ALPHA_R_OP_STORE, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_STORE", /* Name. */
- FALSE, /* Partial_inplace. */
- 0, /* Source mask. */
- MINUS_ONE, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* Subtract the reloc address from the value on the top of the
- relocation stack. */
- HOWTO (ALPHA_R_OP_PSUB, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_PSUB", /* Name. */
- FALSE, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* Shift the value on the top of the relocation stack right by the
- given value. */
- HOWTO (ALPHA_R_OP_PRSHIFT, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_PRSHIFT", /* Name. */
- FALSE, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* Hack. Linkage is done by linker. */
- HOWTO (ALPHA_R_LINKAGE, /* Type. */
- 0, /* Rightshift. */
- 8, /* Size (0 = byte, 1 = short, 2 = long). */
- 256, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "LINKAGE", /* Name. */
- FALSE, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* A 32 bit reference to a symbol. */
- HOWTO (ALPHA_R_REFLONG, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "REFLONG", /* Name. */
- TRUE, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- FALSE), /* PC rel offset. */
-
- /* A 64 bit reference to a procedure, written as 32 bit value. */
- HOWTO (ALPHA_R_CODEADDR, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- FALSE, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "CODEADDR", /* Name. */
- FALSE, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 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
- the relocation code on data from the architecture noted. */
-
-static const struct reloc_howto_struct *
-vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
- bfd_reloc_code_real_type code)
-{
- int alpha_type;
-
- vms_debug2 ((1, "vms_bfd_reloc_type_lookup (%p, %d)\t", abfd, code));
-
- switch (code)
- {
- case BFD_RELOC_16: alpha_type = ALPHA_R_SREL16; break;
- case BFD_RELOC_32: alpha_type = ALPHA_R_REFLONG; break;
- case BFD_RELOC_64: alpha_type = ALPHA_R_REFQUAD; break;
- case BFD_RELOC_CTOR: alpha_type = ALPHA_R_REFQUAD; break;
- case BFD_RELOC_23_PCREL_S2: alpha_type = ALPHA_R_BRADDR; break;
- case BFD_RELOC_ALPHA_HINT: alpha_type = ALPHA_R_HINT; break;
- case BFD_RELOC_16_PCREL: alpha_type = ALPHA_R_SREL16; break;
- case BFD_RELOC_32_PCREL: alpha_type = ALPHA_R_SREL32; break;
- 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;
- }
- vms_debug2 ((2, "reloc is %s\n", alpha_howto_table[alpha_type].name));
- return & alpha_howto_table[alpha_type];
-}
-
-static reloc_howto_type *
-vms_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
- const char *r_name)
-{
- unsigned int i;
-
- for (i = 0;
- i < sizeof (alpha_howto_table) / sizeof (alpha_howto_table[0]);
- i++)
- if (alpha_howto_table[i].name != NULL
- && strcasecmp (alpha_howto_table[i].name, r_name) == 0)
- return &alpha_howto_table[i];
-
- return NULL;
-}
-
-/* Part 4.7, writing an object file. */
-
-/* Set the architecture and machine type in BFD abfd to arch and mach.
- Find the correct pointer to a structure and insert it into the arch_info
- pointer. */
-
-static bfd_boolean
-vms_set_arch_mach (bfd * abfd,
- enum bfd_architecture arch ATTRIBUTE_UNUSED,
- unsigned long mach ATTRIBUTE_UNUSED)
-{
- vms_debug2 ((1, "vms_set_arch_mach (%p, %d, %ld)\n", abfd, arch, mach));
-
- if (arch != bfd_arch_alpha
- && arch != bfd_arch_vax
- && arch != bfd_arch_unknown)
- return FALSE;
-
- return bfd_default_set_arch_mach (abfd, arch, mach);
-}
-
-/* Sets the contents of the section section in BFD abfd to the data starting
- in memory at LOCATION. The data is written to the output section starting
- at offset offset for count bytes.
-
- Normally TRUE is returned, else FALSE. Possible error returns are:
- o bfd_error_no_contents - The output section does not have the
- SEC_HAS_CONTENTS attribute, so nothing can be written to it.
- o and some more too */
-
-static bfd_boolean
-vms_set_section_contents (bfd * abfd,
- asection *section,
- const void * location,
- file_ptr offset,
- bfd_size_type count)
-{
-#if VMS_DEBUG
- vms_debug (1, "vms_set_section_contents (%p, sec %s, loc %p, off %ld, count %d)\n",
- abfd, section->name, location, (long int)offset, (int)count);
- vms_debug (2, "size %d\n", (int) section->size);
-#endif
- if (count == (bfd_size_type)0)
- return TRUE;
-
- if (section->contents == NULL)
- section->contents = bfd_alloc (abfd, section->size);
- if (section->contents == NULL)
- return FALSE;
-
- memcpy (section->contents + offset, location, (size_t) count);
- return TRUE;
-}
-
-static bfd_boolean
-vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr)
-{
- FILE *file = (FILE *)ptr;
-
- fprintf (file, _("structure level: %d\n"), PRIV(hdr_data.hdr_b_strlvl));
- fprintf (file, _("module name : %s\n"), PRIV(hdr_data.hdr_t_name));
- fprintf (file, _("module version : %s\n"), PRIV(hdr_data.hdr_t_version));
- fprintf (file, _("module date : %s\n"), PRIV(hdr_data.hdr_t_date));
- fprintf (file, _("language name : %s\n"), PRIV(hdr_data.hdr_c_lnm));
- fprintf (file, _("source files : %s\n"), PRIV(hdr_data.hdr_c_src));
- fprintf (file, _("title : %s\n"), PRIV(hdr_data.hdr_c_ttl));
-
- return TRUE;
-}
-\f
-const bfd_target vms_alpha_vec =
-{
- "vms-alpha", /* Name. */
- bfd_target_evax_flavour,
- BFD_ENDIAN_LITTLE, /* Data byte order is little. */
- BFD_ENDIAN_LITTLE, /* Header byte order is little. */
-
- (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
- | WP_TEXT | D_PAGED), /* Object flags. */
- (SEC_ALLOC | SEC_LOAD | SEC_RELOC
- | SEC_READONLY | SEC_CODE | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */
- 0, /* symbol_leading_char. */
- ' ', /* ar_pad_char. */
- 15, /* ar_max_namelen. */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16,
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16,
-
- {_bfd_dummy_target, vms_object_p, /* bfd_check_format. */
- _bfd_vms_lib_alpha_archive_p, _bfd_dummy_target},
- {bfd_false, vms_mkobject, /* bfd_set_format. */
- _bfd_vms_lib_mkarchive, bfd_false},
- {bfd_false, vms_write_object_contents, /* bfd_write_contents. */
- _bfd_vms_lib_write_archive_contents, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (vms),
- BFD_JUMP_TABLE_COPY (vms),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
- BFD_JUMP_TABLE_SYMBOLS (vms),
- BFD_JUMP_TABLE_RELOCS (vms),
- BFD_JUMP_TABLE_WRITE (vms),
- BFD_JUMP_TABLE_LINK (_bfd_nolink),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- NULL,
-
- (PTR) 0
-};
-
-const bfd_target vms_vax_vec =
-{
- "vms-vax", /* Name. */
- bfd_target_ovax_flavour,
- BFD_ENDIAN_LITTLE, /* Data byte order is little. */
- BFD_ENDIAN_LITTLE, /* Header byte order is little. */
-
- (HAS_RELOC | HAS_SYMS /* Object flags. */
- | WP_TEXT | D_PAGED
- | HAS_LINENO | HAS_DEBUG | HAS_LOCALS),
-
- (SEC_ALLOC | SEC_LOAD | SEC_RELOC
- | SEC_READONLY | SEC_CODE | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */
- 0, /* symbol_leading_char */
- ' ', /* ar_pad_char */
- 15, /* ar_max_namelen */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */
-
- {_bfd_dummy_target, vms_object_p, /* bfd_check_format. */
- _bfd_dummy_target, _bfd_dummy_target},
- {bfd_false, vms_mkobject, /* bfd_set_format. */
- bfd_false, bfd_false},
- {bfd_false, vms_write_object_contents, /* bfd_write_contents. */
- bfd_false, bfd_false},
-
- BFD_JUMP_TABLE_GENERIC (vms),
- BFD_JUMP_TABLE_COPY (vms),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
- BFD_JUMP_TABLE_SYMBOLS (vms),
- BFD_JUMP_TABLE_RELOCS (vms),
- BFD_JUMP_TABLE_WRITE (vms),
- BFD_JUMP_TABLE_LINK (_bfd_nolink),
- BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-
- NULL,
-
- (PTR) 0
-};
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include <time.h>
-
#undef vms
#ifndef VMS_H
#define VMS_H
-/* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object
- language). */
-
-#define VMS_BLOCK_SIZE 512
-
-/* VMS Text Information and Relocation Records (TIR/ETIR). */
-
-#define TIR_S_C_STA_GBL 0
-#define TIR_S_C_STA_SB 1
-#define TIR_S_C_STA_SW 2
-#define TIR_S_C_STA_LW 3
-#define TIR_S_C_STA_PB 4
-#define TIR_S_C_STA_PW 5
-#define TIR_S_C_STA_PL 6
-#define TIR_S_C_STA_UB 7
-#define TIR_S_C_STA_UW 8
-#define TIR_S_C_STA_BFI 9
-#define TIR_S_C_STA_WFI 10
-#define TIR_S_C_STA_LFI 11
-#define TIR_S_C_STA_EPM 12
-#define TIR_S_C_STA_CKARG 13
-#define TIR_S_C_STA_WPB 14
-#define TIR_S_C_STA_WPW 15
-#define TIR_S_C_STA_WPL 16
-#define TIR_S_C_STA_LSY 17
-#define TIR_S_C_STA_LIT 18
-#define TIR_S_C_STA_LEPM 19
-#define TIR_S_C_MAXSTACOD 19
-#define TIR_S_C_MINSTOCOD 20
-#define TIR_S_C_STO_SB 20
-#define TIR_S_C_STO_SW 21
-#define TIR_S_C_STO_L 22
-#define TIR_S_C_STO_LW 22
-#define TIR_S_C_STO_BD 23
-#define TIR_S_C_STO_WD 24
-#define TIR_S_C_STO_LD 25
-#define TIR_S_C_STO_LI 26
-#define TIR_S_C_STO_PIDR 27
-#define TIR_S_C_STO_PICR 28
-#define TIR_S_C_STO_RSB 29
-#define TIR_S_C_STO_RSW 30
-#define TIR_S_C_STO_RL 31
-#define TIR_S_C_STO_VPS 32
-#define TIR_S_C_STO_USB 33
-#define TIR_S_C_STO_USW 34
-#define TIR_S_C_STO_RUB 35
-#define TIR_S_C_STO_RUW 36
-#define TIR_S_C_STO_B 37
-#define TIR_S_C_STO_W 38
-#define TIR_S_C_STO_RB 39
-#define TIR_S_C_STO_RW 40
-#define TIR_S_C_STO_RIVB 41
-#define TIR_S_C_STO_PIRR 42
-#define TIR_S_C_MAXSTOCOD 42
-#define TIR_S_C_MINOPRCOD 50
-#define TIR_S_C_OPR_NOP 50
-#define TIR_S_C_OPR_ADD 51
-#define TIR_S_C_OPR_SUB 52
-#define TIR_S_C_OPR_MUL 53
-#define TIR_S_C_OPR_DIV 54
-#define TIR_S_C_OPR_AND 55
-#define TIR_S_C_OPR_IOR 56
-#define TIR_S_C_OPR_EOR 57
-#define TIR_S_C_OPR_NEG 58
-#define TIR_S_C_OPR_COM 59
-#define TIR_S_C_OPR_INSV 60
-#define TIR_S_C_OPR_ASH 61
-#define TIR_S_C_OPR_USH 62
-#define TIR_S_C_OPR_ROT 63
-#define TIR_S_C_OPR_SEL 64
-#define TIR_S_C_OPR_REDEF 65
-#define TIR_S_C_OPR_DFLIT 66
-#define TIR_S_C_MAXOPRCOD 66
-#define TIR_S_C_MINCTLCOD 80
-#define TIR_S_C_CTL_SETRB 80
-#define TIR_S_C_CTL_AUGRB 81
-#define TIR_S_C_CTL_DFLOC 82
-#define TIR_S_C_CTL_STLOC 83
-#define TIR_S_C_CTL_STKDL 84
-#define TIR_S_C_MAXCTLCOD 84
-
-#define ETIR_S_C_MINSTACOD 0 /* Minimum store code. */
-#define ETIR_S_C_STA_GBL 0 /* Stack global symbol value. */
-#define ETIR_S_C_STA_LW 1 /* Stack longword. */
-#define ETIR_S_C_STA_QW 2 /* Stack quadword. */
-#define ETIR_S_C_STA_PQ 3 /* Stack psect base + quadword off. */
-#define ETIR_S_C_STA_LI 4 /* Stack literal. */
-#define ETIR_S_C_STA_MOD 5 /* Stack module. */
-#define ETIR_S_C_STA_CKARG 6 /* Check Arguments. */
-#define ETIR_S_C_MAXSTACOD 6 /* Maximum stack code. */
-#define ETIR_S_C_MINSTOCOD 50 /* Minimum store code. */
-#define ETIR_S_C_STO_B 50 /* Store byte. */
-#define ETIR_S_C_STO_W 51 /* Store word. */
-#define ETIR_S_C_STO_LW 52 /* Store longword. */
-#define ETIR_S_C_STO_QW 53 /* Store quadword. */
-#define ETIR_S_C_STO_IMMR 54 /* Store immediate Repeated. */
-#define ETIR_S_C_STO_GBL 55 /* Store global. */
-#define ETIR_S_C_STO_CA 56 /* Store code address. */
-#define ETIR_S_C_STO_RB 57 /* Store relative branch. */
-#define ETIR_S_C_STO_AB 58 /* Store absolute branch. */
-#define ETIR_S_C_STO_OFF 59 /* Store offset within psect. */
-#define ETIR_S_C_STO_IMM 61 /* Store immediate. */
-#define ETIR_S_C_STO_GBL_LW 62 /* Store global Longword. */
-#define ETIR_S_C_STO_LP_PSB 63 /* STO_LP_PSB not valid in level 2 use STC_LP_PSB. */
-#define ETIR_S_C_STO_HINT_GBL 64 /* Store 14 bit HINT at global address. */
-#define ETIR_S_C_STO_HINT_PS 65 /* Store 14 bit HINT at psect + offset */
-#define ETIR_S_C_MAXSTOCOD 65 /* Maximum store code. */
-#define ETIR_S_C_MINOPRCOD 100 /* Minimum operate code. */
-#define ETIR_S_C_OPR_NOP 100 /* No-op. */
-#define ETIR_S_C_OPR_ADD 101 /* Add. */
-#define ETIR_S_C_OPR_SUB 102 /* Subtract. */
-#define ETIR_S_C_OPR_MUL 103 /* Multiply. */
-#define ETIR_S_C_OPR_DIV 104 /* Divide. */
-#define ETIR_S_C_OPR_AND 105 /* Logical AND. */
-#define ETIR_S_C_OPR_IOR 106 /* Logical inclusive OR. */
-#define ETIR_S_C_OPR_EOR 107 /* Logical exclusive OR. */
-#define ETIR_S_C_OPR_NEG 108 /* Negate. */
-#define ETIR_S_C_OPR_COM 109 /* Complement. */
-#define ETIR_S_C_OPR_INSV 110 /* Insert bit field. */
-#define ETIR_S_C_OPR_ASH 111 /* Arithmetic shift. */
-#define ETIR_S_C_OPR_USH 112 /* Unsigned shift. */
-#define ETIR_S_C_OPR_ROT 113 /* Rotate. */
-#define ETIR_S_C_OPR_SEL 114 /* Select one of three longwords on top of stack. */
-#define ETIR_S_C_OPR_REDEF 115 /* Redefine this symbol after pass 2. */
-#define ETIR_S_C_OPR_DFLIT 116 /* Define a literal. */
-#define ETIR_S_C_MAXOPRCOD 116 /* Maximum operate code. */
-#define ETIR_S_C_MINCTLCOD 150 /* Minimum control code. */
-#define ETIR_S_C_CTL_SETRB 150 /* Set relocation base. */
-#define ETIR_S_C_CTL_AUGRB 151 /* Augment relocation base. */
-#define ETIR_S_C_CTL_DFLOC 152 /* Define debug location. */
-#define ETIR_S_C_CTL_STLOC 153 /* Set debug location. */
-#define ETIR_S_C_CTL_STKDL 154 /* Stack debug location. */
-#define ETIR_S_C_MAXCTLCOD 154 /* Maximum control code. */
-#define ETIR_S_C_MINSTCCOD 200 /* Minimum store-conditional code. */
-#define ETIR_S_C_STC_LP 200 /* Store-conditional Linkage Pair. */
-#define ETIR_S_C_STC_LP_PSB 201 /* Store-conditional Linkage Pair with Procedure Signature. */
-#define ETIR_S_C_STC_GBL 202 /* Store-conditional Address at global address. */
-#define ETIR_S_C_STC_GCA 203 /* Store-conditional Code Address at global address. */
-#define ETIR_S_C_STC_PS 204 /* Store-conditional Address at psect + offset. */
-#define ETIR_S_C_STC_NOP_GBL 205 /* Store-conditional NOP at address of global. */
-#define ETIR_S_C_STC_NOP_PS 206 /* Store-conditional NOP at pect + offset. */
-#define ETIR_S_C_STC_BSR_GBL 207 /* Store-conditional BSR at global address. */
-#define ETIR_S_C_STC_BSR_PS 208 /* Store-conditional BSR at pect + offset. */
-#define ETIR_S_C_STC_LDA_GBL 209 /* Store-conditional LDA at global address. */
-#define ETIR_S_C_STC_LDA_PS 210 /* Store-conditional LDA at psect + offset. */
-#define ETIR_S_C_STC_BOH_GBL 211 /* Store-conditional BSR or Hint at global address. */
-#define ETIR_S_C_STC_BOH_PS 212 /* Store-conditional BSR or Hint at pect + offset. */
-#define ETIR_S_C_STC_NBH_GBL 213 /* Store-conditional NOP,BSR or HINT at global address. */
-#define ETIR_S_C_STC_NBH_PS 214 /* Store-conditional NOP,BSR or HINT at psect + offset. */
-#define ETIR_S_C_MAXSTCCOD 214 /* Maximum store-conditional code. */
-
-#define ETIR_S_C_HEADER_SIZE 4 /* Size of the header of a command */
-
-/* VMS Global Symbol Directory Records (GSD/EGSD). */
-
-#define GSD_S_K_ENTRIES 1
-#define GSD_S_C_ENTRIES 1
-#define GSD_S_C_PSC 0
-#define GSD_S_C_SYM 1
-#define GSD_S_C_EPM 2
-#define GSD_S_C_PRO 3
-#define GSD_S_C_SYMW 4
-#define GSD_S_C_EPMW 5
-#define GSD_S_C_PROW 6
-#define GSD_S_C_IDC 7
-#define GSD_S_C_ENV 8
-#define GSD_S_C_LSY 9
-#define GSD_S_C_LEPM 10
-#define GSD_S_C_LPRO 11
-#define GSD_S_C_SPSC 12
-#define GSD_S_C_SYMV 13
-#define GSD_S_C_EPMV 14
-#define GSD_S_C_PROV 15
-#define GSD_S_C_MAXRECTYP 15
-
-#define EGSD_S_K_ENTRIES 2 /* Offset to first entry in record. */
-#define EGSD_S_C_ENTRIES 2 /* Offset to first entry in record. */
-#define EGSD_S_C_PSC 0 /* Psect definition. */
-#define EGSD_S_C_SYM 1 /* Symbol specification. */
-#define EGSD_S_C_IDC 2 /* Random entity check. */
-#define EGSD_S_C_SPSC 5 /* Shareable image psect definition. */
-#define EGSD_S_C_SYMV 6 /* Vectored (dual-valued) versions of SYM. */
-#define EGSD_S_C_SYMM 7 /* Masked versions of SYM. */
-#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_M_REL 8
-#define GPS_S_M_GBL 16
-#define GPS_S_M_SHR 32
-#define GPS_S_M_EXE 64
-#define GPS_S_M_RD 128
-#define GPS_S_M_WRT 256
-#define GPS_S_M_VEC 512
-#define GPS_S_K_NAME 9
-#define GPS_S_C_NAME 9
-
-#define EGPS_S_B_ALIGN 4
-#define EGPS_S_W_FLAGS 6
-#define EGPS_S_L_ALLOC 8
-#define EGPS_S_B_NAMLNG 12
-
-#define EGPS_S_V_PIC 0x0001
-#define EGPS_S_V_LIB 0x0002
-#define EGPS_S_V_OVR 0x0004
-#define EGPS_S_V_REL 0x0008
-#define EGPS_S_V_GBL 0x0010
-#define EGPS_S_V_SHR 0x0020
-#define EGPS_S_V_EXE 0x0040
-#define EGPS_S_V_RD 0x0080
-#define EGPS_S_V_WRT 0x0100
-#define EGPS_S_V_VEC 0x0200
-#define EGPS_S_V_NOMOD 0x0400
-#define EGPS_S_V_COM 0x0800
-#define EGPS_S_V_ALLOC_64BIT 0x1000
-
-/* Symbol Defintion or Reference. */
-#define GSY_S_M_WEAK 1
-#define GSY_S_M_DEF 2
-#define GSY_S_M_UNI 4
-#define GSY_S_M_REL 8
-
-#define EGSY_S_W_FLAGS 6
-
-#define EGSY_S_V_WEAK 0x0001
-#define EGSY_S_V_DEF 0x0002
-#define EGSY_S_V_UNI 0x0004
-#define EGSY_S_V_REL 0x0008
-#define EGSY_S_V_COMM 0x0010
-#define EGSY_S_V_VECEP 0x0020
-#define EGSY_S_V_NORM 0x0040
-#define EGSY_S_V_QUAD_VAL 0x0080
-
-#define LSY_S_M_DEF 2
-#define LSY_S_M_REL 8
-
-#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_BLKBEG 176 /* Beginning of block. */
-#define DST_S_C_BLKEND 177 /* End of block. */
-#define DST_S_C_ENTRY 181
-#define DST_S_C_PSECT 184
-#define DST_S_C_LINE_NUM 185 /* Line Number. */
-#define DST_S_C_LBLORLIT 186
-#define DST_S_C_LABEL 187
-#define DST_S_C_MODBEG 188 /* Beginning of module. */
-#define DST_S_C_MODEND 189 /* End of module. */
-#define DST_S_C_RTNBEG 190 /* Beginning of routine.*/
-#define DST_S_C_RTNEND 191 /* End of routine. */
-
-/* These are used with DST_S_C_LINE_NUM. */
-#define DST_S_C_LINE_NUM_HEADER_SIZE 4
-
-#define DST_S_C_DELTA_PC_W 1 /* Incr PC. */
-#define DST_S_C_INCR_LINUM 2 /* Incr Line #. */
-#define DST_S_C_INCR_LINUM_W 3 /* Incr Line #. */
-#define DST_S_C_SET_LINUM_INCR 4
-#define DST_S_C_SET_LINUM_INCR_W 5
-#define DST_S_C_RESET_LINUM_INCR 6
-#define DST_S_C_BEG_STMT_MODE 7
-#define DST_S_C_END_STMT_MODE 8
-#define DST_S_C_SET_LINE_NUM 9 /* Set Line #. */
-#define DST_S_C_SET_PC 10
-#define DST_S_C_SET_PC_W 11
-#define DST_S_C_SET_PC_L 12
-#define DST_S_C_SET_STMTNUM 13
-#define DST_S_C_TERM 14 /* End of lines. */
-#define DST_S_C_TERM_W 15 /* End of lines. */
-#define DST_S_C_SET_ABS_PC 16 /* Set PC. */
-#define DST_S_C_DELTA_PC_L 17 /* Incr PC. */
-#define DST_S_C_INCR_LINUM_L 18 /* Incr Line #. */
-#define DST_S_C_SET_LINUM_B 19 /* Set Line #. */
-#define DST_S_C_SET_LINUM_L 20 /* Set Line #. */
-#define DST_S_C_TERM_L 21 /* End of lines. */
-/* These are used with DST_S_C_SOURCE */
-#define DST_S_C_SRC_DECLFILE 1 /* Declare source file. */
-#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 DBG_S_C_USINT 0x03
-#define DBG_S_C_ULINT 0x04
-#define DBG_S_C_UQUAD 0x05
-#define DBG_S_C_SCHAR 0x06
-#define DBG_S_C_SSINT 0x07
-#define DBG_S_C_SLINT 0x08
-#define DBG_S_C_SQUAD 0x09
-#define DBG_S_C_REAL4 0x0a
-#define DBG_S_C_REAL8 0x0b /* D_float double. */
-#define DBG_S_C_COMPLX4 0x0c /* 2xF_float complex float. */
-#define DBG_S_C_COMPLX8 0x0d /* 2xD_float complex double. */
-#define DBG_S_C_REAL8_G 0x1b /* G_float double. */
-#define DBG_S_C_COMPLX8_G 0x1d /* 2xG_float complex double. */
-#define DBG_S_C_FUNCTION_ADDR 0x17
-#define DBG_S_C_ADVANCED_TYPE 0xa3
-/* Some of these are just for future reference. [pr]. */
-#define DBG_S_C_UBITA 0x01 /* Unsigned, aligned bit field. */
-#define DBG_S_C_UBITU 0x22 /* Unsigned, unaligned bit field. */
-#define DBG_S_C_SBITA 0x29 /* Signed, aligned bit field. */
-#define DBG_S_C_SBITU 0x2a /* Signed, unaligned bit field. */
-#define DBG_S_C_CSTRING 0x2e /* Asciz ('\0' terminated) string. */
-#define DBG_S_C_WCHAR 0x38 /* Wchar_t. */
-/* These are descriptor class codes. */
-#define DSC_K_CLASS_S 0x01 /* Static (fixed length). */
-#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_ENUM_START 0xa5
-#define DBG_S_C_ENUM_END 0xa6
-#define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */
-#define DBG_S_C_STRUCT_START 0xab
-#define DBG_S_C_STRUCT_END 0xac
-#define DST_K_TYPSPEC 0xaf /* Type specification. */
-/* These codes are used in the generation of the symbol definition records. */
-#define DST_K_VFLAGS_NOVAL 0x80 /* Struct definition only. */
-#define DST_K_VFLAGS_DSC 0xfa /* Descriptor used. */
-#define DST_K_VFLAGS_TVS 0xfb /* Trailing value specified. */
-#define DST_K_VS_FOLLOWS 0xfd /* Value spec follows. */
-#define DST_K_VFLAGS_BITOFFS 0xff /* Value contains bit offset. */
-#define DST_K_VALKIND_LITERAL 0
-#define DST_K_VALKIND_ADDR 1
-#define DST_K_VALKIND_DESC 2
-#define DST_K_VALKIND_REG 3
-#define DST_K_REG_VAX_AP 0x0c /* R12. */
-#define DST_K_REG_VAX_FP 0x0d /* R13. */
-#define DST_K_REG_VAX_SP 0x0e /* R14. */
-#define DST_V_VALKIND 0 /* Offset of valkind field. */
-#define DST_V_INDIRECT 2 /* Offset to indirect bit. */
-#define DST_V_DISP 3 /* Offset to displacement bit. */
-#define DST_V_REGNUM 4 /* Offset to register number. */
-#define DST_M_INDIRECT (1<<DST_V_INDIRECT)
-#define DST_M_DISP (1<<DST_V_DISP)
-#define DBG_C_FUNCTION_PARAM /* 0xc9 */ \
- (DST_K_VALKIND_ADDR|DST_M_DISP|(DST_K_REG_VAX_AP<<DST_V_REGNUM))
-#define DBG_C_LOCAL_SYM /* 0xd9 */ \
- (DST_K_VALKIND_ADDR|DST_M_DISP|(DST_K_REG_VAX_FP<<DST_V_REGNUM))
-/* Kinds of value specifications. */
-#define DST_K_VS_ALLOC_SPLIT 3 /* Split lifetime. */
-/* Kinds of type specifications. */
-#define DST_K_TS_ATOM 0x01 /* Atomic type specification. */
-#define DST_K_TS_DSC 0x02 /* Descriptor type spec. */
-#define DST_K_TS_IND 0x03 /* Indirect type specification. */
-#define DST_K_TS_TPTR 0x04 /* Typed pointer type spec. */
-#define DST_K_TS_PTR 0x05 /* Pointer type spec. */
-#define DST_K_TS_ARRAY 0x07 /* Array type spec. */
-#define DST_K_TS_NOV_LENG 0x0e /* Novel length type spec. */
-/* These are the codes that are used in the suffix records to determine the
- actual data type. */
-#define DBG_S_C_BASIC DST_K_TS_ATOM
-#define DBG_S_C_BASIC_ARRAY DST_K_TS_DSC
-#define DBG_S_C_STRUCT DST_K_TS_IND
-#define DBG_S_C_POINTER DST_K_TS_TPTR
-#define DBG_S_C_VOID DST_K_TS_PTR
-#define DBG_S_C_COMPLEX_ARRAY DST_K_TS_ARRAY
-
-/* VMS Module Header Records (MHD/EMH). */
-
-#define MHD_S_C_MHD 0
-#define MHD_S_C_LNM 1
-#define MHD_S_C_SRC 2
-#define MHD_S_C_TTL 3
-#define MHD_S_C_CPR 4
-#define MHD_S_C_MTC 5
-#define MHD_S_C_GTX 6
-#define MHD_S_C_MAXHDRTYP 6
-
-#define EMH_S_C_MHD 0 /* Main header record. */
-#define EMH_S_C_LNM 1 /* Language name and version. */
-#define EMH_S_C_SRC 2 /* Source file specification. */
-#define EMH_S_C_TTL 3 /* Title text of module. */
-#define EMH_S_C_CPR 4 /* Copyright notice. */
-#define EMH_S_C_MTC 5 /* Maintenance status. */
-#define EMH_S_C_GTX 6 /* General text. */
-#define EMH_S_C_MAXHDRTYP 6 /* Maximum allowable type. */
-
-/* vms.c. */
-
-extern asymbol *_bfd_vms_make_empty_symbol (bfd *);
-extern int _bfd_vms_slurp_object_records (bfd *abfd);
-
-/* vms-gsd.c. */
-
-extern int _bfd_vms_slurp_gsd (bfd *abfd, int objtype);
-extern int _bfd_vms_write_gsd (bfd *abfd, int objtype);
-extern int _bfd_vms_slurp_dbg (bfd *abfd, int objtype);
-extern int _bfd_vms_write_dbg (bfd *abfd, int objtype);
-extern int _bfd_vms_slurp_tbt (bfd *abfd, int objtype);
-extern int _bfd_vms_write_tbt (bfd *abfd, int objtype);
-
-/* vms-misc.c. */
-
-extern int _bfd_vms_get_object_record (bfd *abfd);
-extern int _bfd_vms_get_first_record (bfd *abfd);
+#include <time.h>
-extern char *vms_get_module_name (const char *filename, bfd_boolean);
-extern time_t vms_time_to_time_t (unsigned int hi, unsigned int lo);
-extern time_t vms_rawtime_to_time_t (unsigned char *buf);
+/* Size of a VMS block on disk. */
-/* vms-hdr.c. */
-
-extern int _bfd_vms_slurp_hdr (bfd *abfd, int objtype);
-extern int _bfd_vms_write_hdr (bfd *abfd, int objtype);
-extern int _bfd_vms_slurp_eom (bfd *abfd, int objtype);
-extern int _bfd_vms_write_eom (bfd *abfd, int objtype);
-extern bfd_boolean _bfd_vms_find_nearest_dst_line
- (bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset,
- const char **file, const char **func, unsigned int *line);
-extern int _bfd_vms_slurp_ihd
- (bfd *abfd, unsigned int *isd_offset, unsigned int *ihs_offset);
-extern int _bfd_vms_slurp_isd (bfd *abfd, unsigned int offset);
-extern int _bfd_vms_slurp_ihs (bfd *abfd, unsigned int offset);
-
-/* vms-tir.c. */
-
-extern int _bfd_vms_slurp_tir (bfd *abfd, int objtype);
-extern int _bfd_vms_write_tir (bfd *abfd, int objtype);
-extern int _bfd_vms_slurp_lnk (bfd *abfd, int objtype);
-
-extern int _bfd_vms_slurp_relocs (bfd *abfd);
-extern int _bfd_vms_decode_relocs
- (bfd *abfd, arelent *relocs, asection *section, asymbol **symbols);
-
-/* The r_type field in a reloc is one of the following values. */
-#define ALPHA_R_IGNORE 0
-#define ALPHA_R_REFQUAD 1
-#define ALPHA_R_BRADDR 2
-#define ALPHA_R_HINT 3
-#define ALPHA_R_SREL16 4
-#define ALPHA_R_SREL32 5
-#define ALPHA_R_SREL64 6
-#define ALPHA_R_OP_PUSH 7
-#define ALPHA_R_OP_STORE 8
-#define ALPHA_R_OP_PSUB 9
-#define ALPHA_R_OP_PRSHIFT 10
-#define ALPHA_R_LINKAGE 11
-#define ALPHA_R_REFLONG 12
-#define ALPHA_R_CODEADDR 13
-#define ALPHA_R_NOP 14
-#define ALPHA_R_BSR 15
-#define ALPHA_R_LDA 16
-#define ALPHA_R_BOH 17
-
-/* VMS Object Language (OBJ/EOBJ). */
-
-#define OBJ_S_C_HDR 0 /* VAX moule header record. */
-#define OBJ_S_C_GSD 1 /* VAX glbal symbol definition record. */
-#define OBJ_S_C_TIR 2 /* VAX tet information record. */
-#define OBJ_S_C_EOM 3 /* VAX en of module record. */
-#define OBJ_S_C_DBG 4 /* VAX Deugger information record. */
-#define OBJ_S_C_TBT 5 /* VAX Trceback 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_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_SUBTYP 4
-#define OBJ_S_C_MAXRECSIZ 2048 /* Maximu legal record size. */
-#define EOBJ_S_C_MAXRECSIZ 8192 /* Maximu legal record size. */
-#define OBJ_S_C_STRLVL 0 /* Structre level. */
-#define EOBJ_S_C_STRLVL 2 /* Structre level. */
-#define OBJ_S_C_SYMSIZ 31 /* Maximu symbol length. */
-#define EOBJ_S_C_SYMSIZ 64 /* Maximu symbol length. */
-#define EOBJ_S_C_SECSIZ 31 /* Maximu section name length. */
-#define OBJ_S_C_STOREPLIM -1 /* Maximu repeat count on store commands. */
-#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. */
+#define VMS_BLOCK_SIZE 512
/* Miscellaneous definitions. */
-#if __GNUC__
-typedef unsigned long long uquad;
-#else
-typedef unsigned long uquad;
-#endif
-
#define MAX_OUTREC_SIZE 4096
#define MIN_OUTREC_LUFT 64
-/* VMS module header. */
-
-struct hdr_struct
-{
- char hdr_b_strlvl;
- int hdr_l_arch1;
- int hdr_l_arch2;
- int hdr_l_recsiz;
- char *hdr_t_name;
- char *hdr_t_version;
- char *hdr_t_date;
- char *hdr_c_lnm;
- char *hdr_c_src;
- char *hdr_c_ttl;
-};
-
-#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
-
/* File format. */
+
enum file_format_enum
{
/* Not yet known. */
FF_NATIVE
};
-enum file_type_enum { FT_UNKNOWN, FT_MODULE, FT_IMAGE };
-
-typedef struct vms_symbol_struct
-{
- struct bfd_hash_entry bfd_hash;
- asymbol *symbol;
-} vms_symbol_entry;
-
-/* Stack value for push/pop commands. */
-
-struct stack_struct
-{
- uquad value;
- int psect;
-};
-
-#define STACKSIZE 8192
-
-/* A minimal decoding of DST compilation units. We only decode
- what's needed to get to the line number information. */
-
-struct fileinfo
-{
- char *name;
- unsigned int srec;
-};
-
-struct srecinfo
-{
- struct srecinfo *next;
- unsigned int line;
- unsigned int sfile;
- unsigned int srec;
-};
-
-struct lineinfo
-{
- struct lineinfo *next;
- bfd_vma address;
- unsigned int line;
-};
-
-struct funcinfo
-{
- struct funcinfo *next;
- char *name;
- bfd_vma low;
- bfd_vma high;
-};
+/* VMS records input buffer. */
-struct module
+struct vms_rec_rd
{
- /* Chain the previously read compilation unit. */
- struct module *next;
-
- /* The module name. */
- char *name;
+ /* Buffer and its size. */
+ unsigned char *buf;
+ unsigned int buf_size;
- /* The start offset and size of debug info in the DST section. */
- unsigned int modbeg;
- unsigned int size;
+ /* Current record and its size. */
+ unsigned char *rec;
+ unsigned int rec_size;
- /* The lowest and highest addresses contained in this compilation
- unit as specified in the compilation unit header. */
- bfd_vma low;
- bfd_vma high;
-
- /* The listing line table. */
- struct lineinfo *line_table;
-
- /* The source record table. */
- struct srecinfo *srec_table;
-
- /* A list of the functions found in this module. */
- struct funcinfo *func_table;
-
- /* Current allocation of file_table. */
- unsigned int file_table_count;
-
- /* An array of the files making up this module. */
- struct fileinfo *file_table;
-};
-
-struct vms_private_data_struct
-{
- bfd_boolean is_vax;
- bfd_boolean fixup_done; /* Flag to indicate if all
- section pointers and PRIV(sections)
- are set up correctly. */
- unsigned char *vms_buf; /* record buffer */
- unsigned int buf_size; /* size of record buffer */
- unsigned char *vms_rec; /* record pointer in record buffer */
- unsigned int rec_size; /* record size */
+ /* Input file format. */
enum file_format_enum file_format;
-
- struct hdr_struct hdr_data; /* data from HDR/EMH record */
- struct eom_struct eom_data; /* data from EOM/EEOM record */
- unsigned int section_count; /* # of sections in following array */
- asection **sections; /* array of GSD/EGSD sections */
- unsigned int gsd_sym_count; /* # of GSD/EGSD symbols */
- asymbol **symbols; /* vector of GSD/EGSD symbols */
- struct proc_value *procedure;
-
- struct stack_struct *stack;
- int stackptr;
-
- struct bfd_hash_table *vms_symbol_table;
- struct bfd_symbol **symcache;
- int symnum;
-
- asection *image_section; /* section for image_ptr */
- unsigned char *image_ptr; /* a pointer to section->contents */
-
- unsigned char pdsc[8]; /* procedure descriptor */
-
- struct module *modules; /* list of all compilation units */
-
- struct dst_info *dst_info;
- asection *dst_section;
- unsigned char *dst_ptr_end;
- unsigned int dst_ptr_offsets_count; /* # of offsets in following array */
- unsigned int *dst_ptr_offsets; /* array of saved image_ptr offsets */
-
- /* Shared library support */
- bfd_vma symvva; /* relative virtual address of symbol vector */
-
- /* Output routine storage */
- unsigned char *output_buf; /* output data */
- int push_level;
- int pushed_size;
- int length_pos;
- int output_size;
- int output_alignment;
-
- /* linkage index counter used by conditional store commands */
- int vms_linkage_index;
-
- /* see tc-alpha.c of gas for a description. */
- int flag_hash_long_names; /* -+, hash instead of truncate */
- int flag_show_after_trunc; /* -H, show hashing/truncation */
};
-#define PRIV(name) ((struct vms_private_data_struct *)abfd->tdata.any)->name
+/* VMS records output buffer. */
-/* Used to keep extra VMS specific information for a given section.
+struct vms_rec_wr
+{
+ /* Output buffer. */
+ unsigned char *buf;
- 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.
+ /* Current length of the record. */
+ unsigned short int size;
- reloc_stream is the actual stream of relocation entries. */
+ /* Sub-record start offset. */
+ unsigned short int subrec_offset;
-struct vms_section_data_struct
-{
- bfd_size_type reloc_size;
- unsigned char *reloc_stream;
- bfd_size_type reloc_offset;
- flagword vflags;
+ /* Some records must have a size that is a multiple of the alignment.
+ Mustn't be 0. */
+ unsigned short int align;
};
-#define vms_section_data(sec) \
- ((struct vms_section_data_struct *)sec->used_by_bfd)
-
struct evax_private_udata_struct
{
asymbol *bsym;
int lkindex;
};
-#define SECTION_NAME_TEMPLATE "__SEC__%d"
+/* vms-misc.c. */
+
+#define VMS_DEBUG 1
#if VMS_DEBUG
extern void _bfd_vms_debug (int, char *, ...) ATTRIBUTE_PRINTF_2;
#define vms_debug2(X)
#endif
-extern struct bfd_hash_entry * _bfd_vms_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
-extern void _bfd_vms_get_header_values (bfd *, unsigned char *, int *, int *);
-extern int _bfd_vms_get_record (bfd *abf);
-extern int _bfd_vms_next_record (bfd *abf);
-extern char * _bfd_vms_save_sized_string (unsigned char *, int);
-extern char * _bfd_vms_save_counted_string (unsigned char *);
-extern void _bfd_vms_push (bfd *, uquad, int);
-extern uquad _bfd_vms_pop (bfd *, int *);
-extern void _bfd_vms_output_begin (bfd *, int, int);
-extern void _bfd_vms_output_alignment (bfd *, int);
-extern void _bfd_vms_output_push (bfd *);
-extern void _bfd_vms_output_pop (bfd *);
-extern void _bfd_vms_output_flush (bfd *);
-extern void _bfd_vms_output_end (bfd *);
-extern int _bfd_vms_output_check (bfd *, int);
-extern void _bfd_vms_output_byte (bfd *, unsigned);
-extern void _bfd_vms_output_short (bfd *, unsigned);
-extern void _bfd_vms_output_long (bfd *, unsigned long);
-extern void _bfd_vms_output_quad (bfd *, uquad);
-extern void _bfd_vms_output_counted (bfd *, char *);
-extern void _bfd_vms_output_dump (bfd *, unsigned char *, int);
-extern void _bfd_vms_output_fill (bfd *, int, int);
-extern char * _bfd_vms_length_hash_symbol (bfd *, const char *, int);
-extern vms_symbol_entry * _bfd_vms_enter_symbol (bfd *, char *);
-
-#define EGPS_S_V_NO_SHIFT 16
-
-extern void bfd_vms_set_section_flags (bfd *, asection *, flagword);
+extern char *vms_get_module_name (const char *filename, bfd_boolean);
+extern unsigned char *get_vms_time_string (void);
+extern time_t vms_time_to_time_t (unsigned int hi, unsigned int lo);
+extern time_t vms_rawtime_to_time_t (unsigned char *buf);
+
+extern char *_bfd_vms_save_sized_string (unsigned char *, int);
+extern char *_bfd_vms_save_counted_string (unsigned char *);
+extern void _bfd_vms_output_begin (struct vms_rec_wr *, int);
+extern void _bfd_vms_output_alignment (struct vms_rec_wr *, int);
+extern void _bfd_vms_output_begin_subrec (struct vms_rec_wr *, int);
+extern void _bfd_vms_output_end_subrec (struct vms_rec_wr *);
+extern void _bfd_vms_output_end (bfd *, struct vms_rec_wr *);
+extern int _bfd_vms_output_check (struct vms_rec_wr *, int);
+extern void _bfd_vms_output_byte (struct vms_rec_wr *, unsigned);
+extern void _bfd_vms_output_short (struct vms_rec_wr *, unsigned);
+extern void _bfd_vms_output_long (struct vms_rec_wr *, unsigned long);
+extern void _bfd_vms_output_quad (struct vms_rec_wr *, bfd_vma);
+extern void _bfd_vms_output_counted (struct vms_rec_wr *, char *);
+extern void _bfd_vms_output_dump (struct vms_rec_wr *, unsigned char *, int);
+extern void _bfd_vms_output_fill (struct vms_rec_wr *, int, int);
+
+/* vms-alpha.c */
+
+extern void bfd_vms_set_section_flags (bfd *, asection *, flagword, flagword);
+
#endif /* VMS_H */