Prevent address violation when attempting to disassemble a corrupt score binary.
[deliverable/binutils-gdb.git] / bfd / vms-alpha.c
index 294bd90bed0b6c27c036e712720d4eac3a9cc297..73f6976325f7dc64c6f270673380c9577801e38f 100644 (file)
@@ -1,6 +1,5 @@
 /* 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.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
    Initial version written by Klaus Kaempf (kkaempf@rmi.de)
    Major rewrite by Adacore.
    MA 02110-1301, USA.  */
 
 /* TODO:
-   o  DMT
+   o  overlayed sections
    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
+   o  LIB$INITIALIZE
+   o  protected sections (for messages)
    ...
 */
 
@@ -51,6 +51,7 @@
 #include "vms/eobjrec.h"
 #include "vms/egsd.h"
 #include "vms/egps.h"
+#include "vms/esgps.h"
 #include "vms/eeom.h"
 #include "vms/emh.h"
 #include "vms/eiaf.h"
@@ -63,6 +64,7 @@
 #include "vms/esdfv.h"
 #include "vms/esrf.h"
 #include "vms/egst.h"
+#include "vms/eidc.h"
 #include "vms/dsc.h"
 #include "vms/prt.h"
 #include "vms/internal.h"
@@ -89,6 +91,7 @@
 #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
 
@@ -164,11 +167,11 @@ struct vms_symbol_entry
   unsigned short flags;
 
   /* Section and offset/value of the symbol.  */
-  unsigned int section;
   unsigned int value;
+  asection *section;
 
   /* Section and offset/value for the entry point (only for subprg).  */
-  unsigned int code_section;
+  asection *code_section;
   unsigned int code_value;
 
   /* Symbol vector offset.  */
@@ -268,8 +271,14 @@ struct vms_private_data_struct
 
   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  */
+
+  /* Transfer addresses (entry points).  */
+  bfd_vma transfer_address[4];
+
+  /* Array of GSD sections to get the correspond BFD one.  */
+  unsigned int section_max;            /* Size of the sections array.  */
+  unsigned int section_count;          /* Number of GSD sections.  */
+  asection **sections;
 
   /* Array of raw symbols.  */
   struct vms_symbol_entry **syms;
@@ -291,11 +300,10 @@ struct vms_private_data_struct
   /* 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;
+  /* The DST section.  */
   asection *dst_section;
 
   unsigned int dst_ptr_offsets_count;  /* # of offsets in following array  */
@@ -321,11 +329,7 @@ struct vms_private_data_struct
   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 */
+  unsigned int vms_linkage_index;
 };
 
 #define PRIV2(abfd, name) \
@@ -360,18 +364,18 @@ struct vms_section_data_struct
   ((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);
+struct vms_private_data_struct *bfd_vms_get_data (bfd *);
 
-static int vms_get_remaining_object_record (bfd *abfd, int read_so_far);
+static int vms_get_remaining_object_record (bfd *, unsigned int);
 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,
+static void alpha_vms_add_fixup_lr (struct bfd_link_info *, unsigned int,
                                     bfd_vma);
+static void alpha_vms_add_lw_reloc (struct bfd_link_info *);
+static void alpha_vms_add_qw_reloc (struct bfd_link_info *);
 
 struct vector_type
 {
@@ -431,7 +435,7 @@ struct alpha_vms_link_hash_table
 {
   struct bfd_link_hash_table root;
 
-  /* Vector of shared libaries.  */
+  /* Vector of shared libraries.  */
   struct vector_type shrlibs;
 
   /* Fixup section.  */
@@ -517,9 +521,11 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
       asection *section;
       flagword bfd_flags;
 
+      /* PR 17512: file: 3d9e9fe9.  */
+      if (offset >= PRIV (recrd.rec_size))
+       return FALSE;
       eisd = (struct vms_eisd *)(PRIV (recrd.rec) + offset);
       rec_size = bfd_getl32 (eisd->eisdsize);
-
       if (rec_size == 0)
         break;
 
@@ -545,12 +551,14 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
         what's in each section without examining the data.  This is
         especially true of DWARF debug sections.  */
       bfd_flags = SEC_ALLOC;
+      if (vbn != 0)
+        bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD;
 
       if (flags & EISD__M_EXE)
-       bfd_flags |= SEC_CODE | SEC_HAS_CONTENTS | SEC_LOAD;
+       bfd_flags |= SEC_CODE;
 
       if (flags & EISD__M_NONSHRADR)
-       bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
+       bfd_flags |= SEC_DATA;
 
       if (!(flags & EISD__M_WRT))
        bfd_flags |= SEC_READONLY;
@@ -559,10 +567,10 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
        bfd_flags |= SEC_DATA;
 
       if (flags & EISD__M_FIXUPVEC)
-       bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
+       bfd_flags |= SEC_DATA;
 
       if (flags & EISD__M_CRF)
-       bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD;
+       bfd_flags |= SEC_DATA;
 
       if (flags & EISD__M_GBL)
        {
@@ -614,14 +622,29 @@ 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);
+  unsigned int gstvbn;
+  unsigned int gstsize ATTRIBUTE_UNUSED;
+  unsigned int dstvbn;
+  unsigned int dstsize;
+  unsigned int dmtvbn;
+  unsigned int dmtbytes;
   asection *section;
 
+  /* PR 21611: Check that offset is valid.  */
+  if (offset > PRIV (recrd.rec_size) - (EIHS__L_DMTBYTES + 4))
+    {
+      _bfd_error_handler (_("Unable to read EIHS record at offset %#x"), offset); 
+      bfd_set_error (bfd_error_file_truncated);
+      return FALSE;
+    }
+
+  gstvbn   = bfd_getl32 (p + EIHS__L_GSTVBN);
+  gstsize  = bfd_getl32 (p + EIHS__L_GSTSIZE);
+  dstvbn   = bfd_getl32 (p + EIHS__L_DSTVBN);
+  dstsize  = bfd_getl32 (p + EIHS__L_DSTSIZE);
+  dmtvbn   = bfd_getl32 (p + EIHS__L_DMTVBN);
+  dmtbytes = bfd_getl32 (p + EIHS__L_DMTBYTES);
+
 #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",
@@ -663,25 +686,13 @@ _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset)
 
   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))
+      if (!_bfd_vms_slurp_object_records (abfd))
        return FALSE;
 
       abfd->flags |= HAS_SYMS;
@@ -759,7 +770,7 @@ _bfd_vms_get_object_record (bfd *abfd)
   vms_debug2 ((8, "_bfd_vms_get_obj_record\n"));
 
   /* Skip alignment byte if the current position is odd.  */
-  if (bfd_tell (abfd) & 1)
+  if (PRIV (recrd.file_format) == FF_FOREIGN && (bfd_tell (abfd) & 1))
     {
       if (bfd_bread (PRIV (recrd.buf), 1, abfd) != 1)
         {
@@ -794,7 +805,7 @@ _bfd_vms_get_object_record (bfd *abfd)
    Return the size of the record or 0 on failure.  */
 
 static int
-vms_get_remaining_object_record (bfd *abfd, int read_so_far)
+vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far)
 {
   unsigned int to_read;
 
@@ -803,7 +814,7 @@ vms_get_remaining_object_record (bfd *abfd, int read_so_far)
   /* Extract record size.  */
   PRIV (recrd.rec_size) = bfd_getl16 (PRIV (recrd.rec) + 2);
 
-  if (PRIV (recrd.rec_size) <= 0)
+  if (PRIV (recrd.rec_size) == 0)
     {
       bfd_set_error (bfd_error_file_truncated);
       return 0;
@@ -830,6 +841,9 @@ vms_get_remaining_object_record (bfd *abfd, int read_so_far)
         return 0;
       PRIV (recrd.buf_size) = to_read;
     }
+  /* PR 17512: file: 025-1974-0.004.  */
+  else if (to_read <= read_so_far)
+    return 0;
 
   /* Read the remaining record.  */
   to_read -= read_so_far;
@@ -860,9 +874,12 @@ _bfd_vms_slurp_ehdr (bfd *abfd)
 {
   unsigned char *ptr;
   unsigned char *vms_rec;
+  unsigned char *end;
   int subtype;
 
   vms_rec = PRIV (recrd.rec);
+  /* PR 17512: file: 62736583.  */
+  end = PRIV (recrd.buf) + PRIV (recrd.buf_size);
 
   vms_debug2 ((2, "HDR/EMH\n"));
 
@@ -874,28 +891,42 @@ _bfd_vms_slurp_ehdr (bfd *abfd)
     {
     case EMH__C_MHD:
       /* Module header.  */
+      if (vms_rec + 21 >= end)
+       goto fail;
       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);
+      if ((vms_rec + 20 + vms_rec[20] + 1) >= end)
+       goto fail;
       PRIV (hdr_data).hdr_t_name   = _bfd_vms_save_counted_string (vms_rec + 20);
       ptr = vms_rec + 20 + vms_rec[20] + 1;
+      if ((ptr + *ptr + 1) >= end)
+       goto fail;
       PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
       ptr += *ptr + 1;
+      if (ptr + 17 >= end)
+       goto fail;
       PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
       break;
 
     case EMH__C_LNM:
+      if (vms_rec + PRIV (recrd.rec_size - 6) > end)
+       goto fail;
       PRIV (hdr_data).hdr_c_lnm =
         _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
       break;
 
     case EMH__C_SRC:
+      if (vms_rec + PRIV (recrd.rec_size - 6) > end)
+       goto fail;
       PRIV (hdr_data).hdr_c_src =
         _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
       break;
 
     case EMH__C_TTL:
+      if (vms_rec + PRIV (recrd.rec_size - 6) > end)
+       goto fail;
       PRIV (hdr_data).hdr_c_ttl =
         _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
       break;
@@ -906,6 +937,7 @@ _bfd_vms_slurp_ehdr (bfd *abfd)
       break;
 
     default:
+    fail:
       bfd_set_error (bfd_error_wrong_format);
       return FALSE;
     }
@@ -938,71 +970,70 @@ struct sec_flags_struct
 
 /* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible.  */
 
-static struct sec_flags_struct evax_section_flags[] =
+static const 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) },
+      EGPS__V_SHR,
+      0,
+      EGPS__V_SHR,
+      0 },
     { 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) },
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
+      SEC_CODE | SEC_READONLY,
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
+      SEC_CODE | SEC_READONLY | 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) },
+      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_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | 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) },
+      EGPS__V_REL | EGPS__V_RD,
+      SEC_DATA | SEC_READONLY,
+      EGPS__V_REL | EGPS__V_RD,
+      SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | 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) },
+      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) },
+      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) },
+      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_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | 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) },
+      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_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | 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) },
+      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) },
+      EGPS__V_PIC | EGPS__V_OVR,
+      SEC_DATA | SEC_READONLY,
+      EGPS__V_PIC | EGPS__V_OVR,
+      SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | 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) }
+      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 }
   };
 
-/* Retrieve bfd section flags by name and size.  */
+/* 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,
+vms_secflag_by_name (const struct sec_flags_struct *section_flags,
+                    const char *name,
                     int hassize)
 {
   int i = 0;
@@ -1023,12 +1054,12 @@ vms_secflag_by_name (bfd *abfd ATTRIBUTE_UNUSED,
   return section_flags[i].flags_always;
 }
 
-/* Retrieve vms section flags by name and size.  */
+/* Retrieve VMS section flags by name and size.  */
 
 static flagword
-vms_esecflag_by_name (struct sec_flags_struct *section_flags,
-                     char *name,
-                     int hassize)
+vms_esecflag_by_name (const struct sec_flags_struct *section_flags,
+                     const char *name,
+                      int hassize)
 {
   int i = 0;
 
@@ -1048,23 +1079,12 @@ vms_esecflag_by_name (struct sec_flags_struct *section_flags,
   return section_flags[i].vflags_always;
 }
 
-/* Input routines.  */
+/* Add SYM to the symbol table of ABFD.
+   Return FALSE in case of error.  */
 
-static struct vms_symbol_entry *
-add_symbol (bfd *abfd, const unsigned char *ascic)
+static bfd_boolean
+add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym)
 {
-  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)
@@ -1081,25 +1101,45 @@ add_symbol (bfd *abfd, const unsigned char *ascic)
              (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *)));
         }
       if (PRIV (syms) == NULL)
-        return NULL;
+        return FALSE;
     }
 
-  PRIV (syms)[PRIV (gsd_sym_count)++] = entry;
+  PRIV (syms)[PRIV (gsd_sym_count)++] = sym;
+  return TRUE;
+}
+
+/* Create a symbol whose name is ASCIC and add it to ABFD.
+   Return NULL in case of error.  */
+
+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 (!add_symbol_entry (abfd, entry))
+    return NULL;
   return entry;
 }
 
 /* Read and process EGSD.  Return FALSE on failure.  */
 
 static bfd_boolean
-_bfd_vms_slurp_egsd (bfd * abfd)
+_bfd_vms_slurp_egsd (bfd *abfd)
 {
-  int gsd_type, gsd_size;
-  asection *section;
+  int gsd_type;
+  unsigned int gsd_size;
   unsigned char *vms_rec;
-  flagword new_flags, old_flags;
-  char *name;
   unsigned long base_addr;
-  unsigned long align_addr;
 
   vms_debug2 ((2, "EGSD\n"));
 
@@ -1109,7 +1149,7 @@ _bfd_vms_slurp_egsd (bfd * abfd)
   /* Calculate base address for each section.  */
   base_addr = 0L;
 
-  while (PRIV (recrd.rec_size) > 0)
+  while (PRIV (recrd.rec_size) > 4)
     {
       vms_rec = PRIV (recrd.rec);
 
@@ -1118,44 +1158,94 @@ _bfd_vms_slurp_egsd (bfd * abfd)
 
       vms_debug2 ((3, "egsd_type %d\n", gsd_type));
 
+      /* PR 21615: Check for size overflow.  */
+      if (PRIV (recrd.rec_size) < gsd_size)
+       {
+         _bfd_error_handler (_("Corrupt EGSD record: size (%#x) is larger than remaining space (%#x)"),
+                             gsd_size, PRIV (recrd.rec_size));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+
       switch (gsd_type)
        {
        case EGSD__C_PSC:
+          /* Program section definition.  */
          {
-           /* 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))
+            flagword new_flags, vms_flags;
+            asection *section;
+
+           vms_flags = bfd_getl16 (egps->flags);
+
+            if ((vms_flags & EGPS__V_REL) == 0)
               {
-                new_flags |= SEC_HAS_CONTENTS;
-                if (old_flags & EGPS__V_REL)
-                  new_flags |= SEC_RELOC;
+                /* Use the global absolute section for all
+                   absolute sections.  */
+                section = bfd_abs_section_ptr;
               }
-           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
+            else
+              {
+                char *name;
+                unsigned long align_addr;
+
+                name = _bfd_vms_save_counted_string (&egps->namlng);
+
+                section = bfd_make_section (abfd, name);
+                if (!section)
+                  return FALSE;
+
+                section->filepos = 0;
+                section->size = bfd_getl32 (egps->alloc);
+                section->alignment_power = egps->align;
+
+                vms_section_data (section)->flags = vms_flags;
+                vms_section_data (section)->no_flags = 0;
+
+                new_flags = vms_secflag_by_name (evax_section_flags, name,
+                                                 section->size > 0);
+                if (section->size > 0)
+                  new_flags |= SEC_LOAD;
+                if (!(vms_flags & EGPS__V_NOMOD) && section->size > 0)
+                  {
+                    /* Set RELOC and HAS_CONTENTS if the section is not
+                       demand-zero and not empty.  */
+                    new_flags |= SEC_HAS_CONTENTS;
+                    if (vms_flags & EGPS__V_REL)
+                      new_flags |= SEC_RELOC;
+                  }
+                if (vms_flags & EGPS__V_EXE)
+                  {
+                    /* Set CODE if section is executable.  */
+                    new_flags |= SEC_CODE;
+                    new_flags &= ~SEC_DATA;
+                  }
+                if (!bfd_set_section_flags (abfd, section, new_flags))
+                  return FALSE;
+
+                /* Give a non-overlapping vma to non absolute sections.  */
+                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;
+              }
+
+            /* Append it to the section array.  */
+            if (PRIV (section_count) >= PRIV (section_max))
+              {
+                if (PRIV (section_max) == 0)
+                  PRIV (section_max) = 16;
+                else
+                  PRIV (section_max) *= 2;
+                PRIV (sections) = bfd_realloc_or_free
+                  (PRIV (sections), PRIV (section_max) * sizeof (asection *));
+                if (PRIV (sections) == NULL)
+                  return FALSE;
+              }
+
+            PRIV (sections)[PRIV (section_count)] = section;
+            PRIV (section_count)++;
          }
          break;
 
@@ -1164,6 +1254,7 @@ _bfd_vms_slurp_egsd (bfd * abfd)
             int nameoff;
             struct vms_symbol_entry *entry;
             struct vms_egsy *egsy = (struct vms_egsy *) vms_rec;
+            flagword old_flags;
 
            old_flags = bfd_getl16 (egsy->flags);
            if (old_flags & EGSY__V_DEF)
@@ -1191,14 +1282,15 @@ _bfd_vms_slurp_egsd (bfd * abfd)
                 struct vms_esdf *esdf = (struct vms_esdf *)vms_rec;
 
                entry->value = bfd_getl64 (esdf->value);
-               entry->section = bfd_getl32 (esdf->psindx);
+               entry->section = PRIV (sections)[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);
+                    entry->code_section =
+                      PRIV (sections)[bfd_getl32 (esdf->ca_psindx)];
                   }
               }
          }
@@ -1206,15 +1298,11 @@ _bfd_vms_slurp_egsd (bfd * abfd)
 
        case EGSD__C_SYMG:
          {
-            int nameoff;
             struct vms_symbol_entry *entry;
             struct vms_egst *egst = (struct vms_egst *)vms_rec;
+            flagword old_flags;
 
            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);
 
@@ -1227,7 +1315,11 @@ _bfd_vms_slurp_egsd (bfd * abfd)
 
             entry->symbol_vector = bfd_getl32 (egst->value);
 
-            entry->section = bfd_getl32 (egst->psindx);
+            if (old_flags & EGSY__V_REL)
+              entry->section = PRIV (sections)[bfd_getl32 (egst->psindx)];
+            else
+              entry->section = bfd_abs_section_ptr;
+
             entry->value = bfd_getl64 (egst->lp_2);
 
             if (old_flags & EGSY__V_NORM)
@@ -1235,16 +1327,19 @@ _bfd_vms_slurp_egsd (bfd * abfd)
                 PRIV (norm_sym_count)++;
 
                 entry->code_value = bfd_getl64 (egst->lp_1);
-                entry->code_section = 0;
+                entry->code_section = bfd_abs_section_ptr;
               }
           }
          break;
 
-       case EGSD__C_IDC:
+        case EGSD__C_SPSC:
+        case EGSD__C_IDC:
+          /* Currently ignored.  */
+          break;
        case EGSD__C_SYMM:
        case EGSD__C_SYMV:
        default:
-         (*_bfd_error_handler) (_("Unknown EGSD subtype %d"), gsd_type);
+         _bfd_error_handler (_("Unknown EGSD subtype %d"), gsd_type);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -1275,7 +1370,7 @@ _bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc)
   if (PRIV (stackptr) >= STACKSIZE)
     {
       bfd_set_error (bfd_error_bad_value);
-      (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
+      _bfd_error_handler (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
       exit (1);
     }
 }
@@ -1288,7 +1383,7 @@ _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"));
+      _bfd_error_handler (_("Stack underflow in _bfd_vms_pop"));
       exit (1);
     }
   PRIV (stackptr)--;
@@ -1383,34 +1478,10 @@ dst_retrieve_location (bfd *abfd, unsigned 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)
+image_write (bfd *abfd, unsigned char *ptr, unsigned int size)
 {
 #if VMS_DEBUG
   _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size,
@@ -1418,9 +1489,6 @@ image_write (bfd *abfd, unsigned char *ptr, int size)
   _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);
@@ -1552,7 +1620,7 @@ _bfd_vms_etir_name (int cmd)
 
     default:
       /* These names have not yet been added to this switch statement.  */
-      (*_bfd_error_handler) (_("unknown ETIR command %d"), cmd);
+      _bfd_error_handler (_("unknown ETIR command %d"), cmd);
     }
 
   return NULL;
@@ -1560,14 +1628,16 @@ _bfd_vms_etir_name (int cmd)
 #define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
 
 static void
-_bfd_vms_get_value (bfd *abfd, const unsigned char *ascic,
+_bfd_vms_get_value (bfd *abfd,
+                   const unsigned char *ascic,
+                   const unsigned char *max_ascic,
                     struct bfd_link_info *info,
                     bfd_vma *vma,
                     struct alpha_vms_link_hash_entry **hp)
 {
   char name[257];
-  int len;
-  int i;
+  unsigned int len;
+  unsigned int i;
   struct alpha_vms_link_hash_entry *h;
 
   /* Not linking.  Do not try to resolve the symbol.  */
@@ -1579,6 +1649,14 @@ _bfd_vms_get_value (bfd *abfd, const unsigned char *ascic,
     }
 
   len = *ascic;
+  if (ascic + len >= max_ascic)
+    {
+      _bfd_error_handler (_("Corrupt vms value"));
+      *vma = 0;
+      *hp = NULL;
+      return;
+    }
+
   for (i = 0; i < len; i++)
     name[i] = ascic[i + 1];
   name[i] = 0;
@@ -1598,9 +1676,8 @@ _bfd_vms_get_value (bfd *abfd, const unsigned char *ascic,
     *vma = 0;
   else
     {
-      if (!(*info->callbacks->undefined_symbol)
-          (info, name, abfd, PRIV (image_section), PRIV (image_offset), TRUE))
-        abort ();
+      (*info->callbacks->undefined_symbol)
+       (info, name, abfd, PRIV (image_section), PRIV (image_offset), TRUE);
       *vma = 0;
     }
 }
@@ -1624,7 +1701,8 @@ alpha_vms_sym_to_ctxt (struct alpha_vms_link_hash_entry *h)
         return RELC_SHR_BASE + PRIV2 (h->sym->owner, shr_index);
       else
         {
-          /* Can this happen ?  I'd like to see an example.  */
+          /* Can this happen (non-relocatable symg) ?  I'd like to see
+             an example.  */
           abort ();
         }
     }
@@ -1639,16 +1717,9 @@ alpha_vms_sym_to_ctxt (struct alpha_vms_link_hash_entry *h)
 }
 
 static bfd_vma
-alpha_vms_get_sym_value (unsigned int sect, bfd_vma addr,
-                         struct alpha_vms_link_hash_entry *h)
+alpha_vms_get_sym_value (asection *sect, bfd_vma addr)
 {
-  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;
+  return sect->output_section->vma + sect->output_offset + addr;
 }
 
 static bfd_vma
@@ -1667,6 +1738,10 @@ alpha_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info,
     return vma + sec->vma;
 }
 
+/* Read an ETIR record from ABFD.  If INFO is not null, put the content into
+   the output section (used during linking).
+   Return FALSE in case of error.  */
+
 static bfd_boolean
 _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 {
@@ -1695,10 +1770,19 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
       ptr += 4;
 
+      /* PR 21589 and 21579: Check for a corrupt ETIR record.  */
+      if (cmd_length < 4 || (ptr + cmd_length > maxptr + 4))
+       {
+       corrupt_etir:
+         _bfd_error_handler (_("Corrupt ETIR record encountered"));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+
 #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);
+      _bfd_hexdump (8, ptr, cmd_length - 4, 0);
 #endif
 
       switch (cmd)
@@ -1708,7 +1792,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
              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_get_value (abfd, ptr, maxptr, info, &op1, &h);
           _bfd_vms_push (abfd, op1, alpha_vms_sym_to_ctxt (h));
           break;
 
@@ -1717,6 +1801,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
              stack 32 bit value, sign extend to 64 bit.  */
         case ETIR__C_STA_LW:
+         if (ptr + 4 >= maxptr)
+           goto corrupt_etir;
           _bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE);
           break;
 
@@ -1725,6 +1811,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
              stack 64 bit value of symbol.  */
         case ETIR__C_STA_QW:
+         if (ptr + 8 >= maxptr)
+           goto corrupt_etir;
           _bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE);
           break;
 
@@ -1738,11 +1826,13 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           {
             int psect;
 
+           if (ptr + 12 >= maxptr)
+             goto corrupt_etir;
             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_error_handler (_("bad section index in %s"),
+                                   _bfd_vms_etir_name (cmd));
                 bfd_set_error (bfd_error_bad_value);
                 return FALSE;
               }
@@ -1754,8 +1844,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
         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));
+         _bfd_error_handler (_("unsupported STA cmd %s"),
+                             _bfd_vms_etir_name (cmd));
           return FALSE;
           break;
 
@@ -1788,7 +1878,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
             }
           else if (rel1 & RELC_SHR_BASE)
             {
-              alpha_vms_add_lw_fixup (info, rel1 & RELC_MASK, op1);
+              alpha_vms_add_fixup_lr (info, rel1 & RELC_MASK, op1);
               rel1 = RELC_NONE;
             }
           if (rel1 != RELC_NONE)
@@ -1827,6 +1917,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           {
             int size;
 
+           if (ptr + 4 >= maxptr)
+             goto corrupt_etir;
             size = bfd_getl32 (ptr);
             _bfd_vms_pop (abfd, &op1, &rel1);
             if (rel1 != RELC_NONE)
@@ -1839,7 +1931,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           /* Store global: write symbol value
              arg: cs   global symbol name.  */
         case ETIR__C_STO_GBL:
-          _bfd_vms_get_value (abfd, ptr, info, &op1, &h);
+          _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h);
           if (h && h->sym)
             {
               if (h->sym->typ == EGSD__C_SYMG)
@@ -1851,7 +1943,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
               else
                 {
                   op1 = alpha_vms_get_sym_value (h->sym->section,
-                                                 h->sym->value, h);
+                                                 h->sym->value);
                   alpha_vms_add_qw_reloc (info);
                 }
             }
@@ -1861,7 +1953,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           /* 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);
+          _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h);
           if (h && h->sym)
             {
               if (h->sym->flags & EGSY__V_NORM)
@@ -1875,7 +1967,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
                   else
                     {
                       op1 = alpha_vms_get_sym_value (h->sym->code_section,
-                                                     h->sym->code_value, h);
+                                                     h->sym->code_value);
                       alpha_vms_add_qw_reloc (info);
                     }
                 }
@@ -1906,8 +1998,10 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
              da        data.  */
         case ETIR__C_STO_IMM:
           {
-            int size;
+            unsigned int size;
 
+           if (ptr + 4 >= maxptr)
+             goto corrupt_etir;
             size = bfd_getl32 (ptr);
             image_write (abfd, ptr + 4, size);
           }
@@ -1920,7 +2014,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
              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);
+          _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h);
 #if 0
           abort ();
 #endif
@@ -1930,14 +2024,14 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
         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));
+         _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));
+         _bfd_error_handler (_("%s: not implemented"),
+                             _bfd_vms_etir_name (cmd));
           return FALSE;
           break;
 
@@ -1961,8 +2055,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
              lw        psect index
              qw        offset.  */
         case ETIR__C_STC_PS:
-          (*_bfd_error_handler) (_("%s: not supported"),
-                                 _bfd_vms_etir_name (cmd));
+         _bfd_error_handler (_("%s: not supported"),
+                             _bfd_vms_etir_name (cmd));
           return FALSE;
           break;
 
@@ -1973,7 +2067,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
              da        signature.  */
 
         case ETIR__C_STC_LP_PSB:
-          _bfd_vms_get_value (abfd, ptr + 4, info, &op1, &h);
+          _bfd_vms_get_value (abfd, ptr + 4, maxptr, info, &op1, &h);
           if (h && h->sym)
             {
               if (h->sym->typ == EGSD__C_SYMG)
@@ -1985,9 +2079,9 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
               else
                 {
                   op1 = alpha_vms_get_sym_value (h->sym->code_section,
-                                                 h->sym->code_value, h);
+                                                 h->sym->code_value);
                   op2 = alpha_vms_get_sym_value (h->sym->section,
-                                                h->sym->value, h);
+                                                h->sym->value);
                 }
             }
           else
@@ -2052,8 +2146,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           /* 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));
+         _bfd_error_handler (_("%s: not supported"),
+                             _bfd_vms_etir_name (cmd));
           return FALSE;
           break;
 
@@ -2069,6 +2163,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           /* Augment relocation base: increment image location counter by offset
              arg: lw   offset value.  */
         case ETIR__C_CTL_AUGRB:
+         if (ptr + 4 >= maxptr)
+           goto corrupt_etir;
           op1 = bfd_getl32 (ptr);
           image_inc_ptr (abfd, op1);
           break;
@@ -2192,8 +2288,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           if (rel1 != RELC_NONE || rel2 != RELC_NONE)
             {
             bad_context:
-              (*_bfd_error_handler) (_("invalid use of %s with contexts"),
-                                     _bfd_vms_etir_name (cmd));
+             _bfd_error_handler (_("invalid use of %s with contexts"),
+                                 _bfd_vms_etir_name (cmd));
               return FALSE;
             }
           if ((int)op2 < 0)            /* Shift right.  */
@@ -2208,8 +2304,8 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
         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));
+         _bfd_error_handler (_("%s: not supported"),
+                             _bfd_vms_etir_name (cmd));
           return FALSE;
           break;
 
@@ -2226,7 +2322,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
           break;
 
         default:
-          (*_bfd_error_handler) (_("reserved cmd %d"), cmd);
+         _bfd_error_handler (_("reserved cmd %d"), cmd);
           return FALSE;
           break;
         }
@@ -2263,11 +2359,11 @@ vms_slurp_debug (bfd *abfd)
 
   PRIV (image_section) = section;
   PRIV (image_offset) = section->size;
-  PRIV (image_autoextend) = FALSE;
 
   if (!_bfd_vms_slurp_etir (abfd, NULL))
     return FALSE;
 
+  section->size = PRIV (image_offset);
   return TRUE;
 }
 
@@ -2279,7 +2375,7 @@ _bfd_vms_slurp_edbg (bfd *abfd)
 {
   vms_debug2 ((2, "EDBG\n"));
 
-  abfd->flags |= (HAS_DEBUG | HAS_LINENO);
+  abfd->flags |= HAS_DEBUG | HAS_LINENO;
 
   return vms_slurp_debug (abfd);
 }
@@ -2311,7 +2407,7 @@ _bfd_vms_slurp_eeom (bfd *abfd)
   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_error_handler (_("Object module NOT error-free !\n"));
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -2334,21 +2430,20 @@ _bfd_vms_slurp_eeom (bfd *abfd)
 static bfd_boolean
 _bfd_vms_slurp_object_records (bfd * abfd)
 {
-  int err, new_type, type = -1;
+  bfd_boolean err;
+  int type;
 
   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)
+      type = _bfd_vms_get_object_record (abfd);
+      if (type < 0)
        {
          vms_debug2 ((2, "next_record failed\n"));
          return FALSE;
        }
 
-      type = new_type;
-
       switch (type)
        {
         case EOBJ__C_EMH:
@@ -2372,7 +2467,7 @@ _bfd_vms_slurp_object_records (bfd * abfd)
         default:
           err = FALSE;
        }
-      if (err != TRUE)
+      if (!err)
        {
          vms_debug2 ((2, "slurp type %d failed\n", type));
          return FALSE;
@@ -2415,7 +2510,7 @@ vms_initialize (bfd * abfd)
 static const struct bfd_target *
 alpha_vms_object_p (bfd *abfd)
 {
-  PTR tdata_save = abfd->tdata.any;
+  void *tdata_save = abfd->tdata.any;
   unsigned int test_len;
   unsigned char *buf;
 
@@ -2457,10 +2552,7 @@ alpha_vms_object_p (bfd *abfd)
   PRIV (recrd.rec) = buf;
 
   if (bfd_bread (buf, test_len, abfd) != test_len)
-    {
-      bfd_set_error (bfd_error_file_truncated);
-      goto error_ret;
-    }
+    goto err_wrong_format;
 
   /* Is it an image?  */
   if ((bfd_getl32 (buf) == EIHD__K_MAJORID)
@@ -2474,6 +2566,10 @@ alpha_vms_object_p (bfd *abfd)
       /* Extract the header size.  */
       PRIV (recrd.rec_size) = bfd_getl32 (buf + EIHD__L_SIZE);
 
+      /* The header size is 0 for DSF files.  */
+      if (PRIV (recrd.rec_size) == 0)
+        PRIV (recrd.rec_size) = sizeof (struct vms_eihd);
+
       if (PRIV (recrd.rec_size) > PRIV (recrd.buf_size))
         {
           buf = bfd_realloc_or_free (buf, PRIV (recrd.rec_size));
@@ -2481,7 +2577,6 @@ alpha_vms_object_p (bfd *abfd)
           if (buf == NULL)
             {
               PRIV (recrd.buf) = NULL;
-              bfd_set_error (bfd_error_no_memory);
               goto error_ret;
             }
           PRIV (recrd.buf) = buf;
@@ -2496,10 +2591,7 @@ alpha_vms_object_p (bfd *abfd)
       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;
-            }
+           goto err_wrong_format;
 
           read_so_far += to_read;
           remaining -= to_read;
@@ -2510,16 +2602,19 @@ alpha_vms_object_p (bfd *abfd)
       /* Reset the record pointer.  */
       PRIV (recrd.rec) = buf;
 
+      /* PR 17512: file: 7d7c57c2.  */
+      if (PRIV (recrd.rec_size) < sizeof (struct vms_eihd))
+       goto error_ret;
       vms_debug2 ((2, "file type is image\n"));
 
-      if (_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset) != TRUE)
+      if (!_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset))
         goto err_wrong_format;
 
-      if (_bfd_vms_slurp_eisd (abfd, eisd_offset) != TRUE)
+      if (!_bfd_vms_slurp_eisd (abfd, eisd_offset))
         goto err_wrong_format;
 
       /* EIHS is optional.  */
-      if (eihs_offset != 0 && _bfd_vms_slurp_eihs (abfd, eihs_offset) != TRUE)
+      if (eihs_offset != 0 && !_bfd_vms_slurp_eihs (abfd, eihs_offset))
         goto err_wrong_format;
     }
   else
@@ -2539,10 +2634,10 @@ alpha_vms_object_p (bfd *abfd)
           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)
+          if (type != EOBJ__C_EMH || !_bfd_vms_slurp_ehdr (abfd))
             goto err_wrong_format;
 
-          if (_bfd_vms_slurp_object_records (abfd) != TRUE)
+          if (!_bfd_vms_slurp_object_records (abfd))
             goto err_wrong_format;
         }
       else
@@ -2570,6 +2665,96 @@ alpha_vms_object_p (bfd *abfd)
 \f
 /* Image write.  */
 
+/* Write an EMH/MHD record.  */
+
+static void
+_bfd_vms_write_emh (bfd *abfd)
+{
+  struct vms_rec_wr *recwr = &PRIV (recwr);
+
+  _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);
+}
+
+/* Write an EMH/LMN record.  */
+
+static void
+_bfd_vms_write_lmn (bfd *abfd, const char *name)
+{
+  char version [64];
+  struct vms_rec_wr *recwr = &PRIV (recwr);
+  unsigned int ver = BFD_VERSION / 10000;
+
+  /* LMN.  */
+  _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
+  _bfd_vms_output_short (recwr, EMH__C_LNM);
+  snprintf (version, sizeof (version), "%s %d.%d.%d", name,
+            ver / 10000, (ver / 100) % 100, ver % 100);
+  _bfd_vms_output_dump (recwr, (unsigned char *)version, strlen (version));
+  _bfd_vms_output_end (abfd, recwr);
+}
+
+
+/* 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_alignment (recwr, 2);
+
+  _bfd_vms_output_begin (recwr, EOBJ__C_EEOM);
+  _bfd_vms_output_long (recwr, PRIV (vms_linkage_index + 1) >> 1);
+  _bfd_vms_output_byte (recwr, 0);     /* Completion code.  */
+  _bfd_vms_output_byte (recwr, 0);     /* Fill byte.  */
+
+  if ((abfd->flags & EXEC_P) == 0
+      && 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->target_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;
+}
+
 static void
 vector_grow1 (struct vector_type *vec, size_t elsz)
 {
@@ -2598,6 +2783,8 @@ alpha_vms_file_position_block (bfd *abfd)
   PRIV (file_pos) -= (PRIV (file_pos) % VMS_BLOCK_SIZE);
 }
 
+/* Convert from internal structure SRC to external structure DST.  */
+
 static void
 alpha_vms_swap_eisd_out (struct vms_internal_eisd_map *src,
                          struct vms_eisd *dst)
@@ -2636,6 +2823,9 @@ alpha_vms_append_extra_eisd (bfd *abfd, struct vms_internal_eisd_map *eisd)
   PRIV (gbl_eisd_tail) = eisd;
 }
 
+/* Create an EISD for shared image SHRIMG.
+   Return FALSE in case of error.  */
+
 static bfd_boolean
 alpha_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg)
 {
@@ -2677,6 +2867,9 @@ alpha_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg)
   return TRUE;
 }
 
+/* Create an EISD for section SEC.
+   Return FALSE in case of failure.  */
+
 static bfd_boolean
 alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
 {
@@ -2710,7 +2903,11 @@ alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
   if (!(sec->flags & SEC_READONLY))
     eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
 
-  if (!(sec->flags & SEC_LOAD))
+  /* If relocations or fixup will be applied, make this isect writeable.  */
+  if (sec->flags & SEC_RELOC)
+    eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
+
+  if (!(sec->flags & SEC_HAS_CONTENTS))
     {
       eisd->u.eisd.flags |= EISD__M_DZRO;
       eisd->u.eisd.flags &= ~EISD__M_CRF;
@@ -2732,6 +2929,9 @@ alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
   return TRUE;
 }
 
+/* Layout executable ABFD and write it to the disk.
+   Return FALSE in case of failure.  */
+
 static bfd_boolean
 alpha_vms_write_exec (bfd *abfd)
 {
@@ -2743,7 +2943,11 @@ alpha_vms_write_exec (bfd *abfd)
   struct vms_internal_eisd_map *first_eisd;
   struct vms_internal_eisd_map *eisd;
   asection *dst;
+  asection *dmt;
+  file_ptr gst_filepos = 0;
+  unsigned int lnkflags = 0;
 
+  /* Build the EIHD.  */
   PRIV (file_pos) = EIHD__C_LENGTH;
 
   memset (&eihd, 0, sizeof (eihd));
@@ -2770,7 +2974,6 @@ alpha_vms_write_exec (bfd *abfd)
 
   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);
 
@@ -2788,11 +2991,10 @@ alpha_vms_write_exec (bfd *abfd)
 
   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 (PRIV (transfer_address[0]), eiha->tfradr1);
+  bfd_putl64 (PRIV (transfer_address[1]), eiha->tfradr2);
+  bfd_putl64 (PRIV (transfer_address[2]), eiha->tfradr3);
+  bfd_putl64 (PRIV (transfer_address[3]), eiha->tfradr4);
   bfd_putl64 (0, eiha->inishr);
 
   /* Alloc EIHI.  */
@@ -2806,6 +3008,7 @@ alpha_vms_write_exec (bfd *abfd)
     char *module;
     unsigned int len;
 
+    /* Set module name.  */
     module = vms_get_module_name (bfd_get_filename (abfd), TRUE);
     len = strlen (module);
     if (len > sizeof (eihi->imgnam) - 1)
@@ -2814,16 +3017,22 @@ alpha_vms_write_exec (bfd *abfd)
     memcpy (eihi->imgnam + 1, module, len);
     free (module);
   }
-  bfd_putl32 (0, eihi->linktime + 0);
-  bfd_putl32 (0, eihi->linktime + 4);
+  {
+    unsigned int lo;
+    unsigned int hi;
+
+    /* Set time.  */
+    vms_get_time (&hi, &lo);
+    bfd_putl32 (lo, eihi->linktime + 0);
+    bfd_putl32 (hi, 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$");
+  dst = PRIV (dst_section);
+  dmt = bfd_get_section_by_name (abfd, "$DMT$");
   if (dst != NULL && dst->size != 0)
     {
       eihs = (struct vms_eihs *)((char *) &eihd + PRIV (file_pos));
@@ -2840,7 +3049,7 @@ alpha_vms_write_exec (bfd *abfd)
       bfd_putl32 (0, eihs->dmtsize);
     }
 
-  /* One per section.  */
+  /* One EISD per section.  */
   for (sec = abfd->sections; sec; sec = sec->next)
     {
       if (!alpha_vms_create_eisd_for_section (abfd, sec))
@@ -2916,10 +3125,25 @@ alpha_vms_write_exec (bfd *abfd)
       PRIV (file_pos) += sec->size;
     }
 
+  /* Update EIHS.  */
   if (eihs != NULL && dst != NULL)
     {
       bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn);
       bfd_putl32 (dst->size, eihs->dstsize);
+
+      if (dmt != NULL)
+        {
+          lnkflags |= EIHD__M_DBGDMT;
+          bfd_putl32 ((dmt->filepos / VMS_BLOCK_SIZE) + 1, eihs->dmtvbn);
+          bfd_putl32 (dmt->size, eihs->dmtsize);
+        }
+      if (PRIV (gsd_sym_count) != 0)
+        {
+          alpha_vms_file_position_block (abfd);
+          gst_filepos = PRIV (file_pos);
+          bfd_putl32 ((gst_filepos / VMS_BLOCK_SIZE) + 1, eihs->gstvbn);
+          bfd_putl32 ((PRIV (gsd_sym_count) + 4) / 5 + 4, eihs->gstsize);
+        }
     }
 
   /* Write EISD in hdr.  */
@@ -2929,6 +3153,7 @@ alpha_vms_write_exec (bfd *abfd)
       (eisd, (struct vms_eisd *)((char *)&eihd + eisd->file_pos));
 
   /* Write first block.  */
+  bfd_putl32 (lnkflags, eihd.lnkflags);
   if (bfd_bwrite (&eihd, sizeof (eihd), abfd) != sizeof (eihd))
     return FALSE;
 
@@ -2980,92 +3205,70 @@ alpha_vms_write_exec (bfd *abfd)
         }
     }
 
-  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)
+  /* Write GST.  */
+  if (gst_filepos != 0)
     {
-      c = *p++;
-      hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
-    }
-  return hash;
-}
+      struct vms_rec_wr *recwr = &PRIV (recwr);
+      unsigned int i;
 
-/* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
+      _bfd_vms_write_emh (abfd);
+      _bfd_vms_write_lmn (abfd, "GNU LD");
 
-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;
+      /* PSC for the absolute section.  */
+      _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
+      _bfd_vms_output_long (recwr, 0);
+      _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
+      _bfd_vms_output_short (recwr, 0);
+      _bfd_vms_output_short (recwr, EGPS__V_PIC | EGPS__V_LIB | EGPS__V_RD);
+      _bfd_vms_output_long (recwr, 0);
+      _bfd_vms_output_counted (recwr, ".$$ABS$$.");
+      _bfd_vms_output_end_subrec (recwr);
+      _bfd_vms_output_end (abfd, recwr);
 
-  /* We may need to truncate the symbol, save the hash for later.  */
-  in_len = strlen (in);
+      for (i = 0; i < PRIV (gsd_sym_count); i++)
+        {
+          struct vms_symbol_entry *sym = PRIV (syms)[i];
+          bfd_vma val;
+          bfd_vma ep;
 
-  result = (in_len > maxlen) ? hash_string (in) : 0;
+          if ((i % 5) == 0)
+            {
+              _bfd_vms_output_alignment (recwr, 8);
+              _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
+              _bfd_vms_output_long (recwr, 0);
+            }
+          _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYMG);
+          _bfd_vms_output_short (recwr, 0); /* Data type, alignment.  */
+          _bfd_vms_output_short (recwr, sym->flags);
 
-  old_name = in;
+          if (sym->code_section)
+            ep = alpha_vms_get_sym_value (sym->code_section, sym->code_value);
+          else
+            {
+              BFD_ASSERT (sym->code_value == 0);
+              ep = 0;
+            }
+          val = alpha_vms_get_sym_value (sym->section, sym->value);
+          _bfd_vms_output_quad
+            (recwr, sym->typ == EGSD__C_SYMG ? sym->symbol_vector : val);
+         _bfd_vms_output_quad (recwr, ep);
+         _bfd_vms_output_quad (recwr, val);
+         _bfd_vms_output_long (recwr, 0);
+          _bfd_vms_output_counted (recwr, sym->name);
+          _bfd_vms_output_end_subrec (recwr);
+          if ((i % 5) == 4)
+            _bfd_vms_output_end (abfd, recwr);
+        }
+      if ((i % 5) != 0)
+        _bfd_vms_output_end (abfd, recwr);
 
-  /* Do the length checking.  */
-  if (in_len <= maxlen)
-    i = in_len;
-  else
-    {
-      if (PRIV (flag_hash_long_names))
-       i = maxlen - 9;
-      else
-       i = maxlen;
+      if (!_bfd_vms_write_eeom (abfd))
+        return FALSE;
     }
-
-  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;
+  return TRUE;
 }
+\f
+/* Object write.  */
 
 /* Write section and symbol directory of bfd abfd.  Return FALSE on error.  */
 
@@ -3075,18 +3278,13 @@ _bfd_vms_write_egsd (bfd *abfd)
   asection *section;
   asymbol *symbol;
   unsigned int symnum;
-  int last_index = -1;
-  char dummy_name[10];
-  char *sname;
+  const char *sname;
   flagword new_flags, old_flags;
-  int abs_section_index = 0;
+  int abs_section_index = -1;
+  unsigned int target_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));
+  vms_debug2 ((2, "vms_write_egsd\n"));
 
   /* Egsd is quadword aligned.  */
   _bfd_vms_output_alignment (recwr, 8);
@@ -3094,15 +3292,28 @@ _bfd_vms_write_egsd (bfd *abfd)
   _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
   _bfd_vms_output_long (recwr, 0);
 
-  while (section != 0)
+  /* Number sections.  */
+  for (section = abfd->sections; section != NULL; section = section->next)
+    {
+      if (section->flags & SEC_DEBUGGING)
+        continue;
+      if (!strcmp (section->name, ".vmsdebug"))
+        {
+          section->flags |= SEC_DEBUGGING;
+          continue;
+        }
+      section->target_index = target_index++;
+    }
+
+  for (section = abfd->sections; section != NULL; section = section->next)
     {
       vms_debug2 ((3, "Section #%d %s, %d bytes\n",
-                   section->index, section->name, (int)section->size));
+                   section->target_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;
+      if (section->flags & SEC_DEBUGGING)
+        continue;
 
       /* 13 bytes egsd, max 31 chars name -> should be 44 bytes.  */
       if (_bfd_vms_output_check (recwr, 64) < 0)
@@ -3112,25 +3323,12 @@ _bfd_vms_write_egsd (bfd *abfd)
          _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;
+        vms_slurp_gsd happy.  */
+      sname = section->name;
       if (*sname == '.')
        {
+          /* Remove leading dot.  */
          sname++;
          if ((*sname == 't') && (strcmp (sname, "text") == 0))
            sname = EVAX_CODE_NAME;
@@ -3145,20 +3343,12 @@ _bfd_vms_write_egsd (bfd *abfd)
          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;
-           }
+            sname = EVAX_LITERALS_NAME;
          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
@@ -3178,14 +3368,17 @@ _bfd_vms_write_egsd (bfd *abfd)
       vms_debug2 ((3, "new_flags %x, _raw_size %lu\n",
                    new_flags, (unsigned long)section->size));
 
+      _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
+      _bfd_vms_output_short (recwr, section->alignment_power & 0xff);
       _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;
+      /* If the section is an obsolute one, remind its index as it will be
+         used later for absolute symbols.  */
+      if ((new_flags & EGPS__V_REL) == 0 && abs_section_index < 0)
+        abs_section_index = section->target_index;
     }
 
   /* Output symbols.  */
@@ -3195,33 +3388,54 @@ done:
 
   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;
 
+      /* Work-around a missing feature:  consider __main as the main entry
+         point.  */
+      if (symbol->name[0] == '_' && strcmp (symbol->name, "__main") == 0)
+       bfd_set_start_address (abfd, (bfd_vma)symbol->value);
+
+      /* Only put in the GSD the global and the undefined symbols.  */
       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;
+      if ((old_flags & BSF_GLOBAL) == 0 && !bfd_is_und_section (symbol->section))
+        {
+          /* If the LIB$INITIIALIZE section is present, add a reference to
+             LIB$INITIALIZE symbol.  FIXME: this should be done explicitely
+             in the assembly file.  */
+          if (!((old_flags & BSF_SECTION_SYM) != 0
+                && 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)
+      /* 13 bytes egsd, max 64 chars name -> should be 77 bytes.  Add 16 more
+         bytes for a possible ABS section.  */
+      if (_bfd_vms_output_check (recwr, 80 + 16) < 0)
        {
          _bfd_vms_output_end (abfd, recwr);
          _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
          _bfd_vms_output_long (recwr, 0);
        }
 
+      if ((old_flags & BSF_GLOBAL) != 0
+          && bfd_is_abs_section (symbol->section)
+          && abs_section_index <= 0)
+        {
+          /* Create an absolute section if none was defined.  It is highly
+             unlikely that the name $ABS$ clashes with a user defined
+             non-absolute section name.  */
+          _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
+          _bfd_vms_output_short (recwr, 4);
+          _bfd_vms_output_short (recwr, EGPS__V_SHR);
+          _bfd_vms_output_long (recwr, 0);
+          _bfd_vms_output_counted (recwr, "$ABS$");
+          _bfd_vms_output_end_subrec (recwr);
+
+          abs_section_index = target_index++;
+        }
+
       _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYM);
 
       /* Data type, alignment.  */
@@ -3258,25 +3472,24 @@ done:
            {
              asymbol *sym;
 
-              sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
+              sym =
+                ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
              code_address = sym->value;
-             ca_psindx = sym->section->index;
+             ca_psindx = sym->section->target_index;
            }
          if (bfd_is_abs_section (symbol->section))
            psindx = abs_section_index;
          else
-           psindx = symbol->section->index;
+           psindx = symbol->section->target_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_counted (recwr, symbol->name);
 
       _bfd_vms_output_end_subrec (recwr);
-
     }
 
   _bfd_vms_output_alignment (recwr, 8);
@@ -3292,44 +3505,14 @@ _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);
+  _bfd_vms_write_emh (abfd);
+  _bfd_vms_write_lmn (abfd, "GNU AS");
 
   /* SRC.  */
   _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
@@ -3341,22 +3524,9 @@ _bfd_vms_write_ehdr (bfd *abfd)
 
       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;
+         break;
        }
     }
 
@@ -3404,8 +3574,7 @@ 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"))
+  if (section->flags & SEC_DEBUGGING)
     {
       _bfd_vms_output_begin (recwr, EOBJ__C_ETBT);
 
@@ -3429,7 +3598,7 @@ start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset)
         {
           /* 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_long (recwr, (unsigned long) section->target_index);
           _bfd_vms_output_quad (recwr, offset);
           _bfd_vms_output_end_subrec (recwr);
 
@@ -3529,12 +3698,12 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
 
   _bfd_vms_output_alignment (recwr, 4);
 
-  PRIV (vms_linkage_index) = 1;
+  PRIV (vms_linkage_index) = 0;
 
   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)));
+                   section->target_index, section->name, (int) (section->size)));
 
       if (!(section->flags & SEC_HAS_CONTENTS)
          || bfd_is_com_section (section))
@@ -3557,9 +3726,9 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
          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 (section->reloc_count == 0)
+           _bfd_error_handler
+             (_("SEC_RELOC with no relocs in section %A"), section);
 
 #if VMS_DEBUG
          else
@@ -3593,7 +3762,6 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
              asection *sec = sym->section;
              bfd_boolean defer = defer_reloc_p (rptr);
              unsigned int slen;
-             char *hash;
 
              if (pass2_in_progress)
                {
@@ -3612,8 +3780,8 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
 
                  /* Regular relocs are intertwined with binary data.  */
                  if (curr_addr > addr)
-                   (*_bfd_error_handler) (_("Size error in section %s"),
-                                          section->name);
+                   _bfd_error_handler (_("Size error in section %A"),
+                                       section);
                  size = addr - curr_addr;
                  sto_imm (abfd, section, size, curr_data, curr_addr);
                  curr_data += size;
@@ -3632,13 +3800,11 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                    {
                      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_counted (recwr, sym->name);
                          _bfd_vms_output_end_subrec (recwr);
                          _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
                          _bfd_vms_output_long (recwr, (unsigned long) addend);
@@ -3652,7 +3818,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                        {
                          _bfd_vms_output_begin_subrec
                             (recwr, ETIR__C_STO_GBL_LW);
-                         _bfd_vms_output_counted (recwr, hash);
+                         _bfd_vms_output_counted (recwr, sym->name);
                          _bfd_vms_output_end_subrec (recwr);
                        }
                    }
@@ -3669,7 +3835,8 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                    {
                      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_long (recwr,
+                                            (unsigned long) sec->target_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
@@ -3686,13 +3853,11 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                    {
                      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_counted (recwr, sym->name);
                          _bfd_vms_output_end_subrec (recwr);
                          _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW);
                          _bfd_vms_output_quad (recwr, addend);
@@ -3705,7 +3870,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                      else
                        {
                          _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL);
-                         _bfd_vms_output_counted (recwr, hash);
+                         _bfd_vms_output_counted (recwr, sym->name);
                          _bfd_vms_output_end_subrec (recwr);
                        }
                    }
@@ -3722,7 +3887,8 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                    {
                      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_long (recwr,
+                                            (unsigned long) sec->target_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);
@@ -3738,22 +3904,19 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                  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);
+                   (recwr, (unsigned long) rptr->addend);
+                  if (rptr->addend > PRIV (vms_linkage_index))
+                    PRIV (vms_linkage_index) = rptr->addend;
+                 _bfd_vms_output_counted (recwr, sym->name);
                  _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_counted (recwr, sym->name);
                  _bfd_vms_output_end_subrec (recwr);
                  break;
 
@@ -3765,20 +3928,18 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                  _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);
+                   (recwr, (unsigned long) section->target_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);
+                   (recwr, (unsigned long) section->target_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_counted (recwr, udata->origname);
                  _bfd_vms_output_end_subrec (recwr);
                  break;
 
                case ALPHA_R_BSR:
-                 (*_bfd_error_handler) (_("Spurious ALPHA_R_BSR reloc"));
+                 _bfd_error_handler (_("Spurious ALPHA_R_BSR reloc"));
                  break;
 
                case ALPHA_R_LDA:
@@ -3790,15 +3951,13 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                  _bfd_vms_output_long
                    (recwr, (unsigned long) udata->lkindex + 1);
                  _bfd_vms_output_long
-                   (recwr, (unsigned long) udata->enbsym->section->index);
+                   (recwr, (unsigned long) section->target_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);
+                   (recwr, (unsigned long) udata->bsym->section->target_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_counted (recwr, udata->origname);
                  _bfd_vms_output_end_subrec (recwr);
                  break;
 
@@ -3810,21 +3969,19 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
                  _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);
+                   (recwr, (unsigned long) section->target_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);
+                   (recwr, (unsigned long) section->target_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_counted (recwr, udata->origname);
                  _bfd_vms_output_end_subrec (recwr);
                  break;
 
                default:
-                 (*_bfd_error_handler) (_("Unhandled relocation %s"),
-                                        rptr->howto->name);
+                 _bfd_error_handler (_("Unhandled relocation %s"),
+                                     rptr->howto->name);
                  break;
                }
 
@@ -3836,8 +3993,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
            {
              /* Output rest of section.  */
              if (curr_addr > section->size)
-               (*_bfd_error_handler) (_("Size error in section %s"),
-                                      section->name);
+               _bfd_error_handler (_("Size error in section %A"), section);
              size = section->size - curr_addr;
              sto_imm (abfd, section, size, curr_data, curr_addr);
              curr_data += size;
@@ -3861,41 +4017,6 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
   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
@@ -3911,13 +4032,13 @@ alpha_vms_write_object_contents (bfd *abfd)
     {
       if (abfd->section_count > 0)                     /* we have sections */
         {
-          if (_bfd_vms_write_ehdr (abfd) != TRUE)
+          if (!_bfd_vms_write_ehdr (abfd))
             return FALSE;
-          if (_bfd_vms_write_egsd (abfd) != TRUE)
+          if (!_bfd_vms_write_egsd (abfd))
             return FALSE;
-          if (_bfd_vms_write_etir (abfd, EOBJ__C_ETIR) != TRUE)
+          if (!_bfd_vms_write_etir (abfd, EOBJ__C_ETIR))
             return FALSE;
-          if (_bfd_vms_write_eeom (abfd) != TRUE)
+          if (!_bfd_vms_write_eeom (abfd))
             return FALSE;
         }
     }
@@ -4148,8 +4269,8 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
                  break;
 
                default:
-                 (*_bfd_error_handler) (_("unknown source command %d"),
-                                        cmd);
+                 _bfd_error_handler (_("unknown source command %d"),
+                                     cmd);
                  cmd_length = 2;
                  break;
                }
@@ -4208,31 +4329,31 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
                  break;
 
                case DST__K_SET_LINUM_INCR:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_SET_LINUM_INCR not implemented"));
                  cmd_length = 2;
                  break;
 
                case DST__K_SET_LINUM_INCR_W:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_SET_LINUM_INCR_W not implemented"));
                  cmd_length = 3;
                  break;
 
                case DST__K_RESET_LINUM_INCR:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_RESET_LINUM_INCR not implemented"));
                  cmd_length = 1;
                  break;
 
                case DST__K_BEG_STMT_MODE:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_BEG_STMT_MODE not implemented"));
                  cmd_length = 1;
                  break;
 
                case DST__K_END_STMT_MODE:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_END_STMT_MODE not implemented"));
                  cmd_length = 1;
                  break;
@@ -4259,25 +4380,25 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
                  break;
 
                case DST__K_SET_PC:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_SET_PC not implemented"));
                  cmd_length = 2;
                  break;
 
                case DST__K_SET_PC_W:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_SET_PC_W not implemented"));
                  cmd_length = 3;
                  break;
 
                case DST__K_SET_PC_L:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_SET_PC_L not implemented"));
                  cmd_length = 5;
                  break;
 
                case DST__K_SET_STMTNUM:
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("DST__K_SET_STMTNUM not implemented"));
                  cmd_length = 2;
                  break;
@@ -4321,8 +4442,7 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
                    }
                  else
                    {
-                     (*_bfd_error_handler) (_("unknown line command %d"),
-                                            cmd);
+                     _bfd_error_handler (_("unknown line command %d"), cmd);
                      cmd_length = 2;
                    }
                  break;
@@ -4450,6 +4570,11 @@ build_module_list (bfd *abfd)
       /* 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.  */
+      void *dst = PRIV (dst_section)->contents;
+
+      if (dst == NULL)
+        return NULL;
+
       module = new_module (abfd);
       parse_module (abfd, module, PRIV (dst_section)->contents, -1);
       list = module;
@@ -4529,10 +4654,14 @@ module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr,
    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)
+_bfd_vms_find_nearest_line (bfd *abfd,
+                           asymbol **symbols ATTRIBUTE_UNUSED,
+                           asection *section,
+                           bfd_vma offset,
+                           const char **file,
+                           const char **func,
+                           unsigned int *line,
+                           unsigned int *discriminator)
 {
   struct module *module;
 
@@ -4542,10 +4671,14 @@ _bfd_vms_find_nearest_dst_line (bfd *abfd, asection *section,
   *file = NULL;
   *func = NULL;
   *line = 0;
+  if (discriminator)
+    *discriminator = 0;
 
-  if (PRIV (dst_section) == NULL || !(abfd->flags & (EXEC_P | DYNAMIC)))
+  /* We can't do anything if there is no DST (debug symbol table).  */
+  if (PRIV (dst_section) == NULL)
     return FALSE;
 
+  /* Create the module list - if not already done.  */
   if (PRIV (modules) == NULL)
     {
       PRIV (modules) = build_module_list (abfd);
@@ -4589,7 +4722,7 @@ alpha_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym)
           if (e->flags & EGSY__V_NORM)
             flags |= BSF_FUNCTION;
           value = e->value;
-          sec = PRIV (sections)[e->section];
+          sec = e->section;
         }
       else
         {
@@ -4615,35 +4748,9 @@ alpha_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym)
       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);
-
+      value = e->value;
+      /* sec = e->section; */
       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:
@@ -4793,7 +4900,8 @@ alpha_vms_slurp_relocs (bfd *abfd)
             case ETIR__C_CTL_SETRB:
               if (prev_cmd != ETIR__C_STA_PQ)
                 {
-                  (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                     (_("Unknown reloc %s + %s"), _bfd_vms_etir_name (prev_cmd),
                      _bfd_vms_etir_name (cmd));
                   return FALSE;
@@ -4810,7 +4918,8 @@ alpha_vms_slurp_relocs (bfd *abfd)
                 {
                   if (prev_cmd != ETIR__C_STA_GBL)
                     {
-                      (*_bfd_error_handler)
+                     _bfd_error_handler
+                       /* xgettext:c-format */
                         (_("Unknown reloc %s + %s"), _bfd_vms_etir_name (cmd),
                          _bfd_vms_etir_name (ETIR__C_STA_LW));
                       return FALSE;
@@ -4824,7 +4933,8 @@ alpha_vms_slurp_relocs (bfd *abfd)
                                 /* ALPHA_R_REFQUAD und_section, step 2 */
               if (prev_cmd != -1 && prev_cmd != ETIR__C_STA_GBL)
                 {
-                  (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                     (_("Unknown reloc %s + %s"), _bfd_vms_etir_name (cmd),
                      _bfd_vms_etir_name (ETIR__C_STA_QW));
                   return FALSE;
@@ -4840,9 +4950,10 @@ alpha_vms_slurp_relocs (bfd *abfd)
                   && 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));
+                 /* xgettext:c-format */
+                 _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;
@@ -4852,9 +4963,10 @@ alpha_vms_slurp_relocs (bfd *abfd)
                                 /* 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));
+                 /* xgettext:c-format */
+                 _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;
@@ -4863,9 +4975,10 @@ alpha_vms_slurp_relocs (bfd *abfd)
             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));
+                 /* xgettext:c-format */
+                 _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;
@@ -4875,9 +4988,10 @@ alpha_vms_slurp_relocs (bfd *abfd)
                                   /* 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));
+                 /* xgettext:c-format */
+                 _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;
@@ -4930,8 +5044,8 @@ alpha_vms_slurp_relocs (bfd *abfd)
               continue;
 
             default:
-              (*_bfd_error_handler) (_("Unknown reloc %s"),
-                                     _bfd_vms_etir_name (cmd));
+             _bfd_error_handler (_("Unknown reloc %s"),
+                                 _bfd_vms_etir_name (cmd));
               return FALSE;
             }
 
@@ -4943,10 +5057,17 @@ alpha_vms_slurp_relocs (bfd *abfd)
             /* 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"));
+               _bfd_error_handler (_("Invalid section index in ETIR"));
                 return FALSE;
               }
+
             sec = PRIV (sections)[cur_psect];
+            if (sec == bfd_abs_section_ptr)
+              {
+               _bfd_error_handler (_("Relocation for non-REL psect"));
+                return FALSE;
+              }
+
             vms_sec = vms_section_data (sec);
 
             /* Allocate a reloc entry.  */
@@ -4957,7 +5078,7 @@ alpha_vms_slurp_relocs (bfd *abfd)
                     vms_sec->reloc_max = 64;
                     sec->relocation = bfd_zmalloc
                       (vms_sec->reloc_max * sizeof (arelent));
-                }
+                  }
                 else
                   {
                     vms_sec->reloc_max *= 2;
@@ -4990,8 +5111,8 @@ alpha_vms_slurp_relocs (bfd *abfd)
                     }
                 if (sym == NULL)
                   {
-                    (*_bfd_error_handler) (_("Unknown symbol in command %s"),
-                                           _bfd_vms_etir_name (cmd));
+                   _bfd_error_handler (_("Unknown symbol in command %s"),
+                                       _bfd_vms_etir_name (cmd));
                     reloc->sym_ptr_ptr = NULL;
                   }
                 else
@@ -5053,6 +5174,11 @@ alpha_vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr,
   *relptr = (arelent *) NULL;
   return section->reloc_count;
 }
+
+/* Install a new set of internal relocs.  */
+
+#define alpha_vms_set_reloc _bfd_generic_set_reloc
+
 \f
 /* This is just copied from ecoff-alpha, needs to be fixed probably.  */
 
@@ -5391,7 +5517,7 @@ alpha_vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
       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);
+       _bfd_error_handler (_("reloc (%d) is *UNKNOWN*"), code);
        return NULL;
     }
   vms_debug2 ((2, "reloc is %s\n", alpha_howto_table[alpha_type].name));
@@ -5450,43 +5576,18 @@ alpha_vms_get_synthetic_symtab (bfd *abfd,
       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;
+              sec = e->code_section;
             }
           else
             continue;
           break;
 
         default:
-          abort ();
+          continue;
         }
 
       l = strlen (name);
@@ -5530,6 +5631,7 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
 
   subtype = (unsigned)bfd_getl16 (emh->subtyp);
 
+  /* xgettext:c-format */
   fprintf (file, _("  EMH %u (len=%u): "), subtype, rec_len);
 
   switch (subtype)
@@ -5630,6 +5732,37 @@ exav_bfd_print_egsy_flags (unsigned int flags, FILE *file)
     fputs (_(" QVAL"), file);
 }
 
+static void
+evax_bfd_print_egsd_flags (FILE *file, unsigned int 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);
+}
+
 static void
 evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
 {
@@ -5648,6 +5781,7 @@ evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
       type = (unsigned)bfd_getl16 (e->gsdtyp);
       len = (unsigned)bfd_getl16 (e->gsdsiz);
 
+      /* xgettext:c-format */
       fprintf (file, _("  EGSD entry %2u (type: %u, len: %u): "),
                n, type, len);
       n++;
@@ -5663,32 +5797,7 @@ evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
             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);
+            evax_bfd_print_egsd_flags (file, flags);
             fputc ('\n', file);
             l = bfd_getl32 (egps->alloc);
             fprintf (file, _("   alloc (len): %u (0x%08x)\n"), l, l);
@@ -5696,6 +5805,27 @@ evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
                      egps->namlng, egps->name);
           }
           break;
+        case EGSD__C_SPSC:
+          {
+            struct vms_esgps *esgps = (struct vms_esgps *)e;
+            unsigned int flags = bfd_getl16 (esgps->flags);
+            unsigned int l;
+
+            fprintf (file, _("SPSC - Shared Image Program section def\n"));
+            fprintf (file, _("   alignment  : 2**%u\n"), esgps->align);
+            fprintf (file, _("   flags      : 0x%04x"), flags);
+            evax_bfd_print_egsd_flags (file, flags);
+            fputc ('\n', file);
+            l = bfd_getl32 (esgps->alloc);
+            fprintf (file, _("   alloc (len)   : %u (0x%08x)\n"), l, l);
+            fprintf (file, _("   image offset  : 0x%08x\n"),
+                     (unsigned int)bfd_getl32 (esgps->base));
+            fprintf (file, _("   symvec offset : 0x%08x\n"),
+                     (unsigned int)bfd_getl32 (esgps->value));
+            fprintf (file, _("   name          : %.*s\n"),
+                     esgps->namlng, esgps->name);
+          }
+          break;
         case EGSD__C_SYM:
           {
             struct vms_egsy *egsy = (struct vms_egsy *)e;
@@ -5733,6 +5863,33 @@ evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
               }
           }
           break;
+        case EGSD__C_IDC:
+          {
+            struct vms_eidc *eidc = (struct vms_eidc *)e;
+            unsigned int flags = bfd_getl32 (eidc->flags);
+            unsigned char *p;
+
+            fprintf (file, _("IDC - Ident Consistency check\n"));
+            fprintf (file, _("   flags         : 0x%08x"), flags);
+            if (flags & EIDC__V_BINIDENT)
+              fputs (" BINDENT", file);
+            fputc ('\n', file);
+            fprintf (file, _("   id match      : %x\n"),
+                     (flags >> EIDC__V_IDMATCH_SH) & EIDC__V_IDMATCH_MASK);
+            fprintf (file, _("   error severity: %x\n"),
+                     (flags >> EIDC__V_ERRSEV_SH) & EIDC__V_ERRSEV_MASK);
+            p = eidc->name;
+            fprintf (file, _("   entity name   : %.*s\n"), p[0], p + 1);
+            p += 1 + p[0];
+            fprintf (file, _("   object name   : %.*s\n"), p[0], p + 1);
+            p += 1 + p[0];
+            if (flags & EIDC__V_BINIDENT)
+              fprintf (file, _("   binary ident  : 0x%08x\n"),
+                       (unsigned)bfd_getl32 (p + 1));
+            else
+              fprintf (file, _("   ascii ident   : %.*s\n"), p[0], p + 1);
+          }
+          break;
         case EGSD__C_SYMG:
           {
             struct vms_egst *egst = (struct vms_egst *)e;
@@ -5827,18 +5984,22 @@ evax_bfd_print_hex (FILE *file, const char *pfx,
 static void
 evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf, int is_ps)
 {
+  /* xgettext:c-format */
   fprintf (file, _("    linkage index: %u, replacement insn: 0x%08x\n"),
            (unsigned)bfd_getl32 (buf),
            (unsigned)bfd_getl32 (buf + 16));
+  /* xgettext:c-format */
   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));
+  /* xgettext:c-format */
   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)
+    /* xgettext:c-format */
     fprintf (file, _("    psect idx 3: %u, offset 3: 0x%08x %08x\n"),
              (unsigned)bfd_getl32 (buf + 32),
              (unsigned)bfd_getl32 (buf + 40),
@@ -5852,8 +6013,9 @@ 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;
+  unsigned int sec_len = 0;
 
+  /* xgettext:c-format */
   fprintf (file, _("  %s (len=%u+%u):\n"), name,
            (unsigned)(rec_len - sizeof (struct vms_eobjrec)),
            (unsigned)sizeof (struct vms_eobjrec));
@@ -5869,6 +6031,7 @@ evax_bfd_print_etir (FILE *file, const char *name,
       size = bfd_getl16 (etir->size);
       buf = rec + off + sizeof (struct vms_etir);
 
+      /* xgettext:c-format */
       fprintf (file, _("   (type: %3u, size: 4+%3u): "), type, size - 4);
       switch (type)
         {
@@ -5887,6 +6050,7 @@ evax_bfd_print_etir (FILE *file, const char *name,
           break;
         case ETIR__C_STA_PQ:
           fprintf (file, _("STA_PQ (stack psect base + offset)\n"));
+         /* xgettext:c-format */
           fprintf (file, _("    psect: %u, offset: 0x%08x %08x\n"),
                    (unsigned)bfd_getl32 (buf + 0),
                    (unsigned)bfd_getl32 (buf + 8),
@@ -5951,6 +6115,10 @@ evax_bfd_print_etir (FILE *file, const char *name,
             sec_len += len;
           }
           break;
+        case ETIR__C_STO_GBL_LW:
+          fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"),
+                   buf[0], buf + 1);
+          break;
         case ETIR__C_STO_LP_PSB:
           fprintf (file, _("STO_OFF (store LP with procedure signature)\n"));
           break;
@@ -6019,6 +6187,7 @@ evax_bfd_print_etir (FILE *file, const char *name,
         case ETIR__C_STC_LP_PSB:
           fprintf (file,
                    _("STC_LP_PSB (store cond linkage pair + signature)\n"));
+         /* xgettext:c-format */
           fprintf (file, _("   linkage index: %u, procedure: %.*s\n"),
                    (unsigned)bfd_getl32 (buf), buf[4], buf + 5);
           buf += 4 + 1 + buf[4];
@@ -6026,17 +6195,20 @@ evax_bfd_print_etir (FILE *file, const char *name,
           break;
         case ETIR__C_STC_GBL:
           fprintf (file, _("STC_GBL (store cond global)\n"));
+         /* xgettext:c-format */
           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"));
+         /* xgettext:c-format */
           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,
+                  /* xgettext:c-format */
                    _("   linkage index: %u, psect: %u, offset: 0x%08x %08x\n"),
                    (unsigned)bfd_getl32 (buf),
                    (unsigned)bfd_getl32 (buf + 4),
@@ -6254,6 +6426,7 @@ evax_bfd_print_relocation_records (FILE *file, const unsigned char *rel,
         break;
       base = bfd_getl32 (rel + 4);
 
+      /* xgettext:c-format */
       fprintf (file, _("  bitcount: %u, base addr: 0x%08x\n"),
                count, base);
 
@@ -6267,6 +6440,7 @@ evax_bfd_print_relocation_records (FILE *file, const unsigned char *rel,
           val = bfd_getl32 (rel);
           rel += 4;
 
+         /* xgettext:c-format */
           fprintf (file, _("   bitmap: 0x%08x (count: %u):\n"), val, count);
 
           for (k = 0; k < 32; k++)
@@ -6299,11 +6473,13 @@ evax_bfd_print_address_fixups (FILE *file, const unsigned char *rel)
       count = bfd_getl32 (rel + 0);
       if (count == 0)
         return;
+      /* xgettext:c-format */
       fprintf (file, _("  image %u (%u entries)\n"),
                (unsigned)bfd_getl32 (rel + 4), count);
       rel += 8;
       for (j = 0; j < count; j++)
         {
+         /* xgettext:c-format */
           fprintf (file, _("   offset: 0x%08x, val: 0x%08x\n"),
                    (unsigned)bfd_getl32 (rel + 0),
                    (unsigned)bfd_getl32 (rel + 4));
@@ -6325,6 +6501,7 @@ evax_bfd_print_reference_fixups (FILE *file, const unsigned char *rel)
       count = bfd_getl32 (rel + 0);
       if (count == 0)
         break;
+      /* xgettext:c-format */
       fprintf (file, _("  image %u (%u entries), offsets:\n"),
                (unsigned)bfd_getl32 (rel + 4), count);
       rel += 8;
@@ -6458,6 +6635,7 @@ evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file)
     }
   else
     {
+      /* xgettext:c-format */
       fprintf (file, _("class: %u, dtype: %u, length: %u, pointer: 0x%08x\n"),
                bclass, dtype, len, pointer);
       switch (bclass)
@@ -6473,10 +6651,12 @@ evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file)
                      evax_bfd_get_dsc_name (dsc->dtype));
             evax_bfd_print_indent (indent + 1, file);
             fprintf (file,
+                    /* xgettext:c-format */
                      _("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,
+                    /* xgettext:c-format */
                      _("arsize: %u, a0: 0x%08x\n"),
                      (unsigned)bfd_getl32 (dsc->arsize),
                      (unsigned)bfd_getl32 (dsc->a0));
@@ -6486,7 +6666,7 @@ evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file)
             for (i = 0; i < dsc->dimct; i++)
               {
                 evax_bfd_print_indent (indent + 2, file);
-                fprintf (file, _("[%u]: %u\n"), i + 1,
+                fprintf (file, "[%u]: %u\n", i + 1,
                          (unsigned)bfd_getl32 (b));
                 b += 4;
               }
@@ -6496,6 +6676,7 @@ evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file)
             for (i = 0; i < dsc->dimct; i++)
               {
                 evax_bfd_print_indent (indent + 2, file);
+               /* xgettext:c-format */
                 fprintf (file, _("[%u]: Lower: %u, upper: %u\n"), i + 1,
                          (unsigned)bfd_getl32 (b + 0),
                          (unsigned)bfd_getl32 (b + 4));
@@ -6512,6 +6693,7 @@ evax_bfd_print_desc (const unsigned char *buf, int indent, FILE *file)
                      evax_bfd_get_dsc_name (ubs->dtype));
             evax_bfd_print_indent (indent + 1, file);
             fprintf (file,
+                    /* xgettext:c-format */
                      _("base: %u, pos: %u\n"),
                      (unsigned)bfd_getl32 (ubs->base),
                      (unsigned)bfd_getl32 (ubs->pos));
@@ -6532,6 +6714,7 @@ evax_bfd_print_valspec (const unsigned char *buf, int indent, FILE *file)
   unsigned int len = 5;
 
   evax_bfd_print_indent (indent, file);
+  /* xgettext:c-format */
   fprintf (file, _("vflags: 0x%02x, value: 0x%08x "), vflags, value);
   buf += 5;
 
@@ -6560,6 +6743,7 @@ evax_bfd_print_valspec (const unsigned char *buf, int indent, FILE *file)
       fprintf (file, _("(at bit offset %u)\n"), value);
       break;
     default:
+      /* xgettext:c-format */
       fprintf (file, _("(reg: %u, disp: %u, indir: %u, kind: "),
                (vflags & DST__K_REGNUM_MASK) >> DST__K_REGNUM_SHIFT,
                vflags & DST__K_DISP ? 1 : 0,
@@ -6592,24 +6776,26 @@ evax_bfd_print_typspec (const unsigned char *buf, int indent, FILE *file)
   unsigned int len = (unsigned)bfd_getl16 (buf);
 
   evax_bfd_print_indent (indent, file);
-  fprintf (file, ("len: %2u, kind: %2u "), len, kind);
+  /* xgettext:c-format */
+  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"),
+    /* xgettext:c-format */
+      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"),
+      fprintf (file, _("indirect, defined at 0x%08x\n"),
                (unsigned)bfd_getl32 (buf));
       break;
     case DST__K_TS_TPTR:
-      fprintf (file, ("typed pointer\n"));
+      fprintf (file, _("typed pointer\n"));
       evax_bfd_print_typspec (buf, indent + 1, file);
       break;
     case DST__K_TS_PTR:
-      fprintf (file, ("pointer\n"));
+      fprintf (file, _("pointer\n"));
       break;
     case DST__K_TS_ARRAY:
       {
@@ -6617,30 +6803,30 @@ evax_bfd_print_typspec (const unsigned char *buf, int indent, FILE *file)
         unsigned int vec_len;
         unsigned int i;
 
-        fprintf (file, ("array, dim: %u, bitmap: "), buf[0]);
+        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"));
+        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"));
+                fprintf (file, _("type spec for element:\n"));
               else
-                fprintf (file, ("type spec for subscript %u:\n"), i);
+                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"));
+      fprintf (file, _("*unhandled*\n"));
     }
 }
 
@@ -6667,6 +6853,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
         }
       len = bfd_getl16 (dsth.length);
       type = bfd_getl16 (dsth.type);
+      /* xgettext:c-format */
       fprintf (file, _(" type: %3u, len: %3u (at 0x%08x): "),
                type, len, off);
       if (len == 0)
@@ -6735,6 +6922,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
             const char *name = (const char *)buf + sizeof (*dst);
 
             fprintf (file, _("modbeg\n"));
+           /* xgettext:c-format */
             fprintf (file, _("   flags: %d, language: %u, "
                              "major: %u, minor: %u\n"),
                      dst->flags,
@@ -6757,6 +6945,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
             const char *name = (const char *)buf + sizeof (*dst);
 
             fputs (_("rtnbeg\n"), file);
+           /* xgettext:c-format */
             fprintf (file, _("    flags: %u, address: 0x%08x, "
                              "pd-address: 0x%08x\n"),
                      dst->flags,
@@ -6786,6 +6975,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
           {
             struct vms_dst_epilog *dst = (void *)buf;
 
+           /* xgettext:c-format */
             fprintf (file, _("epilog: flags: %u, count: %u\n"),
                      dst->flags, (unsigned)bfd_getl32 (dst->count));
           }
@@ -6795,6 +6985,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
             struct vms_dst_blkbeg *dst = (void *)buf;
             const char *name = (const char *)buf + sizeof (*dst);
 
+           /* xgettext:c-format */
             fprintf (file, _("blkbeg: address: 0x%08x, name: %.*s\n"),
                      (unsigned)bfd_getl32 (dst->address),
                      name[0], name + 1);
@@ -6828,7 +7019,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
 
             fprintf (file, _("recbeg: name: %.*s\n"), name[0], name + 1);
             evax_bfd_print_valspec (buf, 4, file);
-            fprintf (file, ("    len: %u bits\n"),
+            fprintf (file, _("    len: %u bits\n"),
                      (unsigned)bfd_getl32 (name + 1 + name[0]));
           }
           break;
@@ -6836,6 +7027,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
           fprintf (file, _("recend\n"));
           break;
         case DST__K_ENUMBEG:
+         /* xgettext:c-format */
           fprintf (file, _("enumbeg, len: %u, name: %.*s\n"),
                    buf[0], buf[1], buf + 2);
           break;
@@ -6849,9 +7041,9 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
         case DST__K_LABEL:
           {
             struct vms_dst_label *lab = (void *)buf;
-            fprintf (file, ("label, name: %.*s\n"),
+            fprintf (file, _("label, name: %.*s\n"),
                      lab->name[0], lab->name + 1);
-            fprintf (file, ("    address: 0x%08x\n"),
+            fprintf (file, _("    address: 0x%08x\n"),
                      (unsigned)bfd_getl32 (lab->value));
           }
           break;
@@ -6863,6 +7055,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
 
             fprintf (file, _("discontiguous range (nbr: %u)\n"), cnt);
             for (i = 0; i < cnt; i++, rng += 8)
+             /* xgettext:c-format */
               fprintf (file, _("    address: 0x%08x, size: %u\n"),
                        (unsigned)bfd_getl32 (rng),
                        (unsigned)bfd_getl32 (rng + 4));
@@ -6897,19 +7090,25 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
                     break;
                   case DST__K_INCR_LINUM:
                     val = buf[1];
-                    fprintf (file, _("incr_linum: +%u\n"), val);
+                    fprintf (file, _("incr_linum(b): +%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);
+                    fprintf (file, _("incr_linum_w: +%u\n"), val);
                     line += val;
                     cmdlen = 3;
                     break;
+                  case DST__K_INCR_LINUM_L:
+                    val = bfd_getl32 (buf + 1);
+                    fprintf (file, _("incr_linum_l: +%u\n"), val);
+                    line += val;
+                    cmdlen = 5;
+                    break;
                   case DST__K_SET_LINUM:
-                    line = (unsigned)bfd_getl16 (buf + 1);
-                    fprintf (file, _("set_line_num %u\n"), line);
+                    line = bfd_getl16 (buf + 1);
+                    fprintf (file, _("set_line_num(w) %u\n"), line);
                     cmdlen = 3;
                     break;
                   case DST__K_SET_LINUM_B:
@@ -6918,12 +7117,12 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
                     cmdlen = 2;
                     break;
                   case DST__K_SET_LINUM_L:
-                    line = (unsigned)bfd_getl32 (buf + 1);
+                    line = 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);
+                    pc = bfd_getl32 (buf + 1);
                     fprintf (file, _("set_abs_pc: 0x%08x\n"), pc);
                     cmdlen = 5;
                     break;
@@ -6933,7 +7132,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
                     cmdlen = 5;
                     break;
                   case DST__K_TERM:
-                    fprintf (file, _("term: 0x%02x"), buf[1]);
+                    fprintf (file, _("term(b): 0x%02x"), buf[1]);
                     pc += buf[1];
                     fprintf (file, _("        pc: 0x%08x\n"), pc);
                     cmdlen = 2;
@@ -6951,6 +7150,7 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
                         fprintf (file, _("delta pc +%-4d"), -cmd);
                         line++;  /* FIXME: curr increment.  */
                         pc += -cmd;
+                       /* xgettext:c-format */
                         fprintf (file, _("    pc: 0x%08x line: %5u\n"),
                                  pc, line);
                         cmdlen = 1;
@@ -6985,10 +7185,12 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
                       struct vms_dst_src_decl_src *src = (void *)(buf + 1);
                       const char *name;
 
+                     /* xgettext:c-format */
                       fprintf (file, _("   declfile: len: %u, flags: %u, "
                                        "fileid: %u\n"),
                                src->length, src->flags,
                                (unsigned)bfd_getl16 (src->fileid));
+                     /* xgettext:c-format */
                       fprintf (file, _("   rms: cdt: 0x%08x %08x, "
                                        "ebk: 0x%08x, ffb: 0x%04x, "
                                        "rfo: %u\n"),
@@ -7092,9 +7294,11 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
       fprintf (file, _("cannot read EIHD\n"));
       return;
     }
+  /* xgettext:c-format */
   fprintf (file, _("EIHD: (size: %u, nbr blocks: %u)\n"),
            (unsigned)bfd_getl32 (eihd.size),
            (unsigned)bfd_getl32 (eihd.hdrblkcnt));
+  /* xgettext:c-format */
   fprintf (file, _(" majorid: %u, minorid: %u\n"),
            (unsigned)bfd_getl32 (eihd.majorid),
            (unsigned)bfd_getl32 (eihd.minorid));
@@ -7112,6 +7316,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
       name = _("unknown");
       break;
     }
+  /* xgettext:c-format */
   fprintf (file, _(" image type: %u (%s)"), val, name);
 
   val = (unsigned)bfd_getl32 (eihd.subtype);
@@ -7127,12 +7332,14 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
       name = _("unknown");
       break;
     }
+  /* xgettext:c-format */
   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);
+  /* xgettext:c-format */
   fprintf (file, _(" offsets: isd: %u, activ: %u, symdbg: %u, "
                    "imgid: %u, patch: %u\n"),
            eisd_off, eiha_off, eihs_off, eihi_off,
@@ -7146,6 +7353,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
                    " version array off: %u\n"),
            eihvn_off);
   fprintf (file,
+          /* xgettext:c-format */
            _(" img I/O count: %u, nbr channels: %u, req pri: %08x%08x\n"),
            (unsigned)bfd_getl32 (eihd.imgiocnt),
            (unsigned)bfd_getl32 (eihd.iochancnt),
@@ -7182,6 +7390,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
   if (val & EIHD__M_EXT_BIND_SECT)
     fprintf (file, " EXT_BIND_SECT");
   fprintf (file, "\n");
+  /* xgettext:c-format */
   fprintf (file, _(" ident: 0x%08x, sysver: 0x%08x, "
                    "match ctrl: %u, symvect_size: %u\n"),
            (unsigned)bfd_getl32 (eihd.ident),
@@ -7194,6 +7403,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
     {
       eihef_off = bfd_getl32 (eihd.ext_fixup_off);
       eihnp_off = bfd_getl32 (eihd.noopt_psect_off);
+      /* xgettext:c-format */
       fprintf (file, _(", ext fixup offset: %u, no_opt psect off: %u"),
                eihef_off, eihnp_off);
     }
@@ -7289,7 +7499,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
                 fputs (_("*unknown*        "), file);
                 break;
               }
-            fprintf (file, _(": %u.%u\n"),
+            fprintf (file, ": %u.%u\n",
                      (unsigned)bfd_getl16 (ver.major),
                      (unsigned)bfd_getl16 (ver.minor));
           }
@@ -7307,18 +7517,23 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
         }
       fprintf (file, _("Image activation:  (size=%u)\n"),
                (unsigned)bfd_getl32 (eiha.size));
+      /* xgettext:c-format */
       fprintf (file, _(" First address : 0x%08x 0x%08x\n"),
                (unsigned)bfd_getl32 (eiha.tfradr1_h),
                (unsigned)bfd_getl32 (eiha.tfradr1));
+      /* xgettext:c-format */
       fprintf (file, _(" Second address: 0x%08x 0x%08x\n"),
                (unsigned)bfd_getl32 (eiha.tfradr2_h),
                (unsigned)bfd_getl32 (eiha.tfradr2));
+      /* xgettext:c-format */
       fprintf (file, _(" Third address : 0x%08x 0x%08x\n"),
                (unsigned)bfd_getl32 (eiha.tfradr3_h),
                (unsigned)bfd_getl32 (eiha.tfradr3));
+      /* xgettext:c-format */
       fprintf (file, _(" Fourth address: 0x%08x 0x%08x\n"),
                (unsigned)bfd_getl32 (eiha.tfradr4_h),
                (unsigned)bfd_getl32 (eiha.tfradr4));
+      /* xgettext:c-format */
       fprintf (file, _(" Shared image  : 0x%08x 0x%08x\n"),
                (unsigned)bfd_getl32 (eiha.inishr_h),
                (unsigned)bfd_getl32 (eiha.inishr));
@@ -7333,6 +7548,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
           fprintf (file, _("cannot read EIHI\n"));
           return;
         }
+      /* xgettext:c-format */
       fprintf (file, _("Image identification: (major: %u, minor: %u)\n"),
                (unsigned)bfd_getl32 (eihi.majorid),
                (unsigned)bfd_getl32 (eihi.minorid));
@@ -7357,19 +7573,23 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
           fprintf (file, _("cannot read EIHS\n"));
           return;
         }
+      /* xgettext:c-format */
       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);
+      /* xgettext:c-format */
+      fprintf (file, _(" debug symbol table : vbn: %u, size: %u (0x%x)\n"),
+               dst_vbn, dst_size, dst_size);
       gst_vbn = bfd_getl32 (eihs.gstvbn);
       gst_size = bfd_getl32 (eihs.gstsize);
+      /* xgettext:c-format */
       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);
+      /* xgettext:c-format */
       fprintf (file, _(" debug module table : vbn: %u, size: %u\n"),
                dmt_vbn, dmt_size);
     }
@@ -7393,6 +7613,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
           /* Next block.  */
           eisd_off = (eisd_off + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
         }
+      /* xgettext:c-format */
       fprintf (file, _("Image section descriptor: (major: %u, minor: %u, "
                        "size: %u, offset: %u)\n"),
                (unsigned)bfd_getl32 (eisd.majorid),
@@ -7400,6 +7621,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
                len, eisd_off);
       if (len == 0)
         break;
+      /* xgettext:c-format */
       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),
@@ -7442,6 +7664,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
           eiaf_vbn = bfd_getl32 (eisd.vbn);
           eiaf_size = bfd_getl32 (eisd.secsize);
         }
+      /* xgettext:c-format */
       fprintf (file, _(" vbn: %u, pfc: %u, matchctl: %u type: %u ("),
                (unsigned)bfd_getl32 (eisd.vbn),
                eisd.pfc, eisd.matchctl, eisd.type);
@@ -7471,6 +7694,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
         }
       fputs (_(")\n"), file);
       if (val & EISD__M_GBL)
+       /* xgettext:c-format */
         fprintf (file, _(" ident: 0x%08x, name: %.*s\n"),
                  (unsigned)bfd_getl32 (eisd.ident),
                  eisd.gblnam[0], eisd.gblnam + 1);
@@ -7499,7 +7723,8 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
             }
           count = bfd_getl16 (dmth.psect_count);
           fprintf (file,
-                   _(" module address: 0x%08x, size: 0x%08x, (%u psect)\n"),
+                  /* xgettext:c-format */
+                   _(" module offset: 0x%08x, size: 0x%08x, (%u psects)\n"),
                    (unsigned)bfd_getl32 (dmth.modbeg),
                    (unsigned)bfd_getl32 (dmth.size), count);
           dmt_size -= sizeof (dmth);
@@ -7512,6 +7737,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
                   fprintf (file, _("cannot read DMT psect\n"));
                   return;
                 }
+             /* xgettext:c-format */
               fprintf (file, _("  psect start: 0x%08x, length: %u\n"),
                        (unsigned)bfd_getl32 (dmtp.start),
                        (unsigned)bfd_getl32 (dmtp.length));
@@ -7567,12 +7793,15 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
         }
       eiaf = (struct vms_eiaf *)buf;
       fprintf (file,
+              /* xgettext:c-format */
                _("Image activator fixup: (major: %u, minor: %u)\n"),
                (unsigned)bfd_getl32 (eiaf->majorid),
                (unsigned)bfd_getl32 (eiaf->minorid));
+      /* xgettext:c-format */
       fprintf (file, _("  iaflink : 0x%08x %08x\n"),
                (unsigned)bfd_getl32 (eiaf->iaflink + 0),
                (unsigned)bfd_getl32 (eiaf->iaflink + 4));
+      /* xgettext:c-format */
       fprintf (file, _("  fixuplnk: 0x%08x %08x\n"),
                (unsigned)bfd_getl32 (eiaf->fixuplnk + 0),
                (unsigned)bfd_getl32 (eiaf->fixuplnk + 4));
@@ -7582,22 +7811,27 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
                (unsigned)bfd_getl32 (eiaf->flags));
       qrelfixoff = bfd_getl32 (eiaf->qrelfixoff);
       lrelfixoff = bfd_getl32 (eiaf->lrelfixoff);
+      /* xgettext:c-format */
       fprintf (file, _("  qrelfixoff: %5u, lrelfixoff: %5u\n"),
                qrelfixoff, lrelfixoff);
       qdotadroff = bfd_getl32 (eiaf->qdotadroff);
       ldotadroff = bfd_getl32 (eiaf->ldotadroff);
+      /* xgettext:c-format */
       fprintf (file, _("  qdotadroff: %5u, ldotadroff: %5u\n"),
                qdotadroff, ldotadroff);
       codeadroff = bfd_getl32 (eiaf->codeadroff);
       lpfixoff = bfd_getl32 (eiaf->lpfixoff);
+      /* xgettext:c-format */
       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);
+      /* xgettext:c-format */
       fprintf (file, _("  shlstoff  : %5u, shrimgcnt : %5u\n"),
                shlstoff, shrimgcnt);
+      /* xgettext:c-format */
       fprintf (file, _("  shlextra  : %5u, permctx   : %5u\n"),
                (unsigned)bfd_getl32 (eiaf->shlextra),
                (unsigned)bfd_getl32 (eiaf->permctx));
@@ -7615,6 +7849,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
           for (j = 0; j < shrimgcnt; j++, shl++)
             {
               fprintf (file,
+                      /* xgettext:c-format */
                        _("  %u: size: %u, flags: 0x%02x, name: %.*s\n"),
                        j, shl->size, shl->flags,
                        shl->imgnam[0], shl->imgnam + 1);
@@ -7647,7 +7882,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
         }
       if (lpfixoff != 0)
         {
-          fprintf (file, _(" Linkage Pairs Referece Fixups:\n"));
+          fprintf (file, _(" Linkage Pairs Reference Fixups:\n"));
           evax_bfd_print_reference_fixups (file, buf + lpfixoff);
         }
       if (chgprtoff)
@@ -7661,6 +7896,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
             {
               unsigned int prot = bfd_getl32 (eicp->newprt);
               fprintf (file,
+                      /* xgettext:c-format */
                        _("  base: 0x%08x %08x, size: 0x%08x, prot: 0x%08x "),
                        (unsigned)bfd_getl32 (eicp->baseva + 4),
                        (unsigned)bfd_getl32 (eicp->baseva + 0),
@@ -7745,7 +7981,7 @@ vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr)
 \f
 /* Linking.  */
 
-/* Slurp an ordered set of VMS object records.  */
+/* Slurp ETIR/EDBG/ETBT VMS object records.  */
 
 static bfd_boolean
 alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
@@ -7758,8 +7994,6 @@ alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
     return FALSE;
 
-  PRIV (image_autoextend) = FALSE;
-
   cur_section = NULL;
   cur_offset = 0;
 
@@ -7769,6 +8003,7 @@ alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
     {
       if (info->strip == strip_all || info->strip == strip_debugger)
         {
+          /* Discard the DST section.  */
           dst_offset = 0;
           dst_section = NULL;
         }
@@ -7805,9 +8040,7 @@ alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
             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:
@@ -7844,8 +8077,11 @@ alpha_vms_add_fixup_lp (struct bfd_link_info *info, bfd *src, bfd *shlib)
   sl->has_fixups = TRUE;
   VEC_APPEND_EL (sl->lp, bfd_vma,
                  sect->output_section->vma + sect->output_offset + offset);
+  sect->output_section->flags |= SEC_RELOC;
 }
 
+/* Add a code address fixup at address SECT + OFFSET to SHLIB. */
+
 static void
 alpha_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib)
 {
@@ -7858,8 +8094,11 @@ alpha_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib)
   sl->has_fixups = TRUE;
   VEC_APPEND_EL (sl->ca, bfd_vma,
                  sect->output_section->vma + sect->output_offset + offset);
+  sect->output_section->flags |= SEC_RELOC;
 }
 
+/* Add a quad word relocation fixup at address SECT + OFFSET to SHLIB. */
+
 static void
 alpha_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src,
                         bfd *shlib, bfd_vma vec)
@@ -7875,25 +8114,19 @@ alpha_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src,
   r = VEC_APPEND (sl->qr, struct alpha_vms_vma_ref);
   r->vma = sect->output_section->vma + sect->output_offset + offset;
   r->ref = vec;
+  sect->output_section->flags |= SEC_RELOC;
 }
 
 static void
-alpha_vms_add_lw_fixup (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+alpha_vms_add_fixup_lr (struct bfd_link_info *info ATTRIBUTE_UNUSED,
                         unsigned int shr ATTRIBUTE_UNUSED,
                         bfd_vma vec ATTRIBUTE_UNUSED)
 {
+  /* Not yet supported.  */
   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
+/* Add relocation.  FIXME: Not yet emitted.  */
 
 static void
 alpha_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
@@ -7985,9 +8218,9 @@ alpha_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
         h = NULL;
 
       h_root = (struct bfd_link_hash_entry *) h;
-      if (_bfd_generic_link_add_one_symbol
-          (info, abfd, sym.name, sym.flags, sym.section, sym.value,
-           NULL, FALSE, FALSE, &h_root) == FALSE)
+      if (!_bfd_generic_link_add_one_symbol (info, abfd, sym.name, sym.flags,
+                                            sym.section, sym.value, NULL,
+                                            FALSE, FALSE, &h_root))
         return FALSE;
       h = (struct alpha_vms_link_hash_entry *) h_root;
 
@@ -8078,7 +8311,10 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
 
       if (element->archive_pass == -1 || element->archive_pass == pass)
-        continue;
+        {
+          /* Next symbol if this archive is wrong or already handled.  */
+          continue;
+        }
 
       if (! bfd_check_format (element, bfd_object))
         {
@@ -8100,10 +8336,10 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
       /* 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))
+      if (!(*info->callbacks
+           ->add_archive_element) (info, element, h->root.string, &element))
+       continue;
+      if (!alpha_vms_link_add_object_symbols (element, info))
        return FALSE;
 
       orig_element->archive_pass = pass;
@@ -8144,6 +8380,8 @@ alpha_vms_build_fixups (struct bfd_link_info *info)
   unsigned int ca_sz = 0;
   unsigned int qr_sz = 0;
   unsigned int shrimg_cnt = 0;
+  unsigned int chgprt_num = 0;
+  unsigned int chgprt_sz = 0;
   struct vms_eiaf *eiaf;
   unsigned int off;
   asection *sec;
@@ -8191,9 +8429,20 @@ alpha_vms_build_fixups (struct bfd_link_info *info)
   if (ca_sz + lp_sz + qr_sz == 0)
     return TRUE;
 
+  /* Add an eicp entry for the fixup itself.  */
+  chgprt_num = 1;
+  for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
+    {
+      /* This isect could be made RO or EXE after relocations are applied.  */
+      if ((sec->flags & SEC_RELOC) != 0
+          && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
+        chgprt_num++;
+    }
+  chgprt_sz = 4 + chgprt_num * sizeof (struct vms_eicp);
+
   /* Allocate section content (round-up size)  */
   sz = sizeof (struct vms_eiaf) + shrimg_cnt * sizeof (struct vms_shl)
-    + ca_sz + lp_sz + qr_sz;
+    + ca_sz + lp_sz + qr_sz + chgprt_sz;
   sz = (sz + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1);
   content = bfd_zalloc (info->output_bfd, sz);
   if (content == NULL)
@@ -8356,9 +8605,118 @@ alpha_vms_build_fixups (struct bfd_link_info *info)
           bfd_putl32 (0, content + off + 4);
           off += 8;
         }
+    }
 
-      /* CA fixups.  */
+  /* Write the change protection table.  */
+  bfd_putl32 (off, eiaf->chgprtoff);
+  bfd_putl32 (chgprt_num, content + off);
+  off += 4;
+
+  for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
+    {
+      struct vms_eicp *eicp;
+      unsigned int prot;
+
+      if ((sec->flags & SEC_LINKER_CREATED) != 0 &&
+          strcmp (sec->name, "$FIXUP$") == 0)
+        prot = PRT__C_UREW;
+      else if ((sec->flags & SEC_RELOC) != 0
+               && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
+        prot = PRT__C_UR;
+      else
+        continue;
+
+      eicp = (struct vms_eicp *)(content + off);
+      bfd_putl64 (sec->vma - t->base_addr, eicp->baseva);
+      bfd_putl32 ((sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1),
+                  eicp->size);
+      bfd_putl32 (prot, eicp->newprt);
+      off += sizeof (struct vms_eicp);
+    }
+
+  return TRUE;
+}
+
+/* Called by bfd_hash_traverse to fill the symbol table.
+   Return FALSE in case of failure.  */
+
+static bfd_boolean
+alpha_vms_link_output_symbol (struct bfd_hash_entry *bh, void *infov)
+{
+  struct bfd_link_hash_entry *hc = (struct bfd_link_hash_entry *) bh;
+  struct bfd_link_info *info = (struct bfd_link_info *)infov;
+  struct alpha_vms_link_hash_entry *h;
+  struct vms_symbol_entry *sym;
+
+  if (hc->type == bfd_link_hash_warning)
+    {
+      hc = hc->u.i.link;
+      if (hc->type == bfd_link_hash_new)
+       return TRUE;
+    }
+  h = (struct alpha_vms_link_hash_entry *) hc;
+
+  switch (h->root.type)
+    {
+    case bfd_link_hash_undefined:
+      return TRUE;
+    case bfd_link_hash_new:
+    case bfd_link_hash_warning:
+      abort ();
+    case bfd_link_hash_undefweak:
+      return TRUE;
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+      {
+        asection *sec = h->root.u.def.section;
+
+        /* FIXME: this is certainly a symbol from a dynamic library.  */
+        if (bfd_is_abs_section (sec))
+          return TRUE;
+
+        if (sec->owner->flags & DYNAMIC)
+          return TRUE;
+      }
+      break;
+    case bfd_link_hash_common:
+      break;
+    case bfd_link_hash_indirect:
+      return TRUE;
+    }
+
+  /* Do not write not kept symbols.  */
+  if (info->strip == strip_some
+      && bfd_hash_lookup (info->keep_hash, h->root.root.string,
+                          FALSE, FALSE) != NULL)
+    return TRUE;
+
+  if (h->sym == NULL)
+    {
+      /* This symbol doesn't come from a VMS object.  So we suppose it is
+         a data.  */
+      int len = strlen (h->root.root.string);
+
+      sym = (struct vms_symbol_entry *)bfd_zalloc (info->output_bfd,
+                                                   sizeof (*sym) + len);
+      if (sym == NULL)
+        abort ();
+      sym->namelen = len;
+      memcpy (sym->name, h->root.root.string, len);
+      sym->name[len] = 0;
+      sym->owner = info->output_bfd;
+
+      sym->typ = EGSD__C_SYMG;
+      sym->data_type = 0;
+      sym->flags = EGSY__V_DEF | EGSY__V_REL;
+      sym->symbol_vector = h->root.u.def.value;
+      sym->section = h->root.u.def.section;
+      sym->value = h->root.u.def.value;
     }
+  else
+    sym = h->sym;
+
+  if (!add_symbol_entry (info->output_bfd, sym))
+    return FALSE;
 
   return TRUE;
 }
@@ -8372,6 +8730,16 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   asection *fixupsec;
   bfd_vma base_addr;
   bfd_vma last_addr;
+  asection *dst;
+  asection *dmt;
+
+  if (bfd_link_relocatable (info))
+    {
+      /* FIXME: we do not yet support relocatable link.  It is not obvious
+         how to do it for debug infos.  */
+      (*info->callbacks->einfo)(_("%P: relocatable link is not supported\n"));
+      return FALSE;
+    }
 
   bfd_get_outsymbols (abfd) = NULL;
   bfd_get_symcount (abfd) = 0;
@@ -8415,12 +8783,17 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
     }
 #endif
 
-  /* Find entry point.  */
+  /* Generate the symbol table.  */
+  BFD_ASSERT (PRIV (syms) == NULL);
+  if (info->strip != strip_all)
+    bfd_hash_traverse (&info->hash->table, alpha_vms_link_output_symbol, info);
+
+  /* Find the entry point.  */
   if (bfd_get_start_address (abfd) == 0)
     {
       bfd *startbfd = NULL;
 
-      for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+      for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
         {
           /* Consider only VMS object files.  */
           if (sub->xvec != abfd->xvec)
@@ -8434,6 +8807,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
               && !(PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR))
             {
               (*info->callbacks->einfo)
+               /* xgettext:c-format */
                 (_("%P: multiple entry points: in modules %B and %B\n"),
                  startbfd, sub);
               continue;
@@ -8454,7 +8828,24 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
         }
     }
 
-  /* Allocate content.  */
+  /* Set transfer addresses.  */
+  {
+    int i;
+    struct bfd_link_hash_entry *h;
+
+    i = 0;
+    PRIV (transfer_address[i++]) = 0xffffffff00000340ULL;      /* SYS$IMGACT */
+    h = bfd_link_hash_lookup (info->hash, "LIB$INITIALIZE", FALSE, FALSE, TRUE);
+    if (h != NULL && h->type == bfd_link_hash_defined)
+      PRIV (transfer_address[i++]) =
+        alpha_vms_get_sym_value (h->u.def.section, h->u.def.value);
+    PRIV (transfer_address[i++]) = bfd_get_start_address (abfd);
+    while (i < 4)
+      PRIV (transfer_address[i++]) = 0;
+  }
+
+  /* Allocate contents.
+     Also compute the virtual base address.  */
   base_addr = (bfd_vma)-1;
   last_addr = 0;
   for (o = abfd->sections; o != NULL; o = o->next)
@@ -8472,8 +8863,12 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
           if (o->vma + o->size > last_addr)
             last_addr = o->vma + o->size;
         }
+      /* Clear the RELOC flags.  Currently we don't support incremental
+         linking.  We use the RELOC flag for computing the eicp entries.  */
+      o->flags &= ~SEC_RELOC;
     }
 
+  /* Create the fixup section.  */
   fixupsec = bfd_make_section_anyway_with_flags
     (info->output_bfd, "$FIXUP$",
      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
@@ -8485,8 +8880,25 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   alpha_vms_link_hash (info)->fixup = fixupsec;
   alpha_vms_link_hash (info)->base_addr = base_addr;
 
+  /* Create the DMT section, if necessary.  */
+  BFD_ASSERT (PRIV (dst_section) == NULL);
+  dst = bfd_get_section_by_name (abfd, "$DST$");
+  if (dst != NULL && dst->size == 0)
+    dst = NULL;
+  if (dst != NULL)
+    {
+      PRIV (dst_section) = dst;
+      dmt = bfd_make_section_anyway_with_flags
+        (info->output_bfd, "$DMT$",
+         SEC_DEBUGGING | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
+      if (dmt == NULL)
+        return FALSE;
+    }
+  else
+    dmt = NULL;
+
   /* Read all sections from the inputs.  */
-  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
       if (sub->flags & DYNAMIC)
         {
@@ -8498,7 +8910,8 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
         return FALSE;
     }
 
-  /* Handle all the link order information for the sections.  */
+  /* Handle all the link order information for the sections.
+     Note: past this point, it is not possible to create new sections.  */
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       for (p = o->map_head.link_order; p != NULL; p = p->next)
@@ -8524,6 +8937,81 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   if (!alpha_vms_build_fixups (info))
     return FALSE;
 
+  /* Compute the DMT.  */
+  if (dmt != NULL)
+    {
+      int pass;
+      unsigned char *contents = NULL;
+
+      /* In pass 1, compute the size.  In pass 2, write the DMT contents.  */
+      for (pass = 0; pass < 2; pass++)
+        {
+          unsigned int off = 0;
+
+          /* For each object file (ie for each module).  */
+          for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+            {
+              asection *sub_dst;
+              struct vms_dmt_header *dmth = NULL;
+              unsigned int psect_count;
+
+              /* Skip this module if it has no DST.  */
+              sub_dst = PRIV2 (sub, dst_section);
+              if (sub_dst == NULL || sub_dst->size == 0)
+                continue;
+
+              if (pass == 1)
+                {
+                  /* Write the header.  */
+                  dmth = (struct vms_dmt_header *)(contents + off);
+                  bfd_putl32 (sub_dst->output_offset, dmth->modbeg);
+                  bfd_putl32 (sub_dst->size, dmth->size);
+                }
+
+              off += sizeof (struct vms_dmt_header);
+              psect_count = 0;
+
+              /* For each section (ie for each psect).  */
+              for (o = sub->sections; o != NULL; o = o->next)
+                {
+                  /* Only consider interesting sections.  */
+                  if (!(o->flags & SEC_ALLOC))
+                    continue;
+                  if (o->flags & SEC_LINKER_CREATED)
+                    continue;
+
+                  if (pass == 1)
+                    {
+                      /* Write an entry.  */
+                      struct vms_dmt_psect *dmtp;
+
+                      dmtp = (struct vms_dmt_psect *)(contents + off);
+                      bfd_putl32 (o->output_offset + o->output_section->vma,
+                                  dmtp->start);
+                      bfd_putl32 (o->size, dmtp->length);
+                      psect_count++;
+                    }
+                  off += sizeof (struct vms_dmt_psect);
+                }
+              if (pass == 1)
+                bfd_putl32 (psect_count, dmth->psect_count);
+            }
+
+          if (pass == 0)
+            {
+              contents = bfd_zalloc (info->output_bfd, off);
+              if (contents == NULL)
+                return FALSE;
+              dmt->contents = contents;
+              dmt->size = off;
+            }
+          else
+            {
+              BFD_ASSERT (off == dmt->size);
+            }
+        }
+    }
+
   return TRUE;
 }
 
@@ -8551,9 +9039,17 @@ alpha_vms_get_section_contents (bfd *abfd, asection *section,
       return FALSE;
     }
 
-  /* Alloc in memory and read ETIRs.  */
-  BFD_ASSERT (section->contents == NULL);
+  /* If the section is already in memory, just copy it.  */
+  if (section->flags & SEC_IN_MEMORY)
+    {
+      BFD_ASSERT (section->contents != NULL);
+      memcpy (buf, section->contents + offset, count);
+      return TRUE;
+    }
+  if (section->size == 0)
+    return TRUE;
 
+  /* Alloc in memory and read ETIRs.  */
   for (sec = abfd->sections; sec; sec = sec->next)
     {
       BFD_ASSERT (sec->contents == NULL);
@@ -8568,8 +9064,8 @@ alpha_vms_get_section_contents (bfd *abfd, asection *section,
   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;
+    if (sec->contents)
+      sec->flags |= SEC_IN_MEMORY;
   memcpy (buf, section->contents + offset, count);
   return TRUE;
 }
@@ -8637,9 +9133,9 @@ vms_close_and_cleanup (bfd * abfd)
     {
       /* Last step on VMS is to convert the file to variable record length
         format.  */
-      if (bfd_cache_close (abfd) != TRUE)
+      if (!bfd_cache_close (abfd))
        return FALSE;
-      if (vms_convert_to_var_unix_filename (abfd->filename) != TRUE)
+      if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename))
        return FALSE;
     }
 #endif
@@ -8654,38 +9150,19 @@ 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);
+  vms_debug2 ((1, "vms_new_section_hook (%p, [%u]%s)\n",
+               abfd, section->index, section->name));
 
-  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;
+  if (! bfd_set_section_alignment (abfd, section, 0))
+    return FALSE;
 
-  vms_debug2 ((7, "%d: %s\n", section->index, section->name));
+  vms_debug2 ((7, "%u: %s\n", section->index, section->name));
 
   amt = sizeof (struct vms_section_data_struct);
-  section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
+  section->used_by_bfd = 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);
 }
@@ -8753,7 +9230,7 @@ vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED,
   if (ret == NULL)
     return;
 
-  if (sec == 0)
+  if (sec == NULL)
     ret->type = 'U';
   else if (bfd_is_com_section (sec))
     ret->type = 'C';
@@ -8763,14 +9240,15 @@ vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED,
     ret->type = 'U';
   else if (bfd_is_ind_section (sec))
     ret->type = 'I';
-  else if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
+  else if ((symbol->flags & BSF_FUNCTION)
+           || (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 = '-';
+    ret->type = '?';
 
   if (ret->type != 'U')
     ret->value = symbol->value + symbol->section->vma;
@@ -8786,7 +9264,6 @@ 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
@@ -8859,6 +9336,7 @@ bfd_vms_get_data (bfd *abfd)
 #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_define_start_stop      bfd_generic_define_start_stop
 #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
@@ -8874,12 +9352,16 @@ bfd_vms_get_data (bfd *abfd)
    ((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_get_symbol_version_string \
+  _bfd_nosymbols_get_symbol_version_string
+
 #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_find_nearest_line        _bfd_vms_find_nearest_line
+#define alpha_vms_find_line                _bfd_nosymbols_find_line
 #define alpha_vms_bfd_is_local_label_name  vms_bfd_is_local_label_name
 
 /* Generic table.  */
@@ -8894,6 +9376,7 @@ bfd_vms_get_data (bfd *abfd)
 
 #define alpha_vms_bfd_relax_section bfd_generic_relax_section
 #define alpha_vms_bfd_gc_sections bfd_generic_gc_sections
+#define alpha_vms_bfd_lookup_section_flags bfd_generic_lookup_section_flags
 #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
@@ -8901,7 +9384,7 @@ bfd_vms_get_data (bfd *abfd)
   _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_define_start_stop bfd_generic_define_start_stop
 #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
@@ -8916,8 +9399,9 @@ bfd_vms_get_data (bfd *abfd)
   _bfd_nodynamic_get_dynamic_reloc_upper_bound
 #define alpha_vms_canonicalize_dynamic_reloc \
   _bfd_nodynamic_canonicalize_dynamic_reloc
+#define alpha_vms_bfd_link_check_relocs              _bfd_generic_link_check_relocs
 
-const bfd_target vms_alpha_vec =
+const bfd_target alpha_vms_vec =
 {
   "vms-alpha",                 /* Name.  */
   bfd_target_evax_flavour,
@@ -8932,6 +9416,7 @@ const bfd_target vms_alpha_vec =
   0,                           /* symbol_leading_char.  */
   ' ',                         /* ar_pad_char.  */
   15,                          /* ar_max_namelen.  */
+  0,                           /* match priority.  */
   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
   bfd_getl16, bfd_getl_signed_16, bfd_putl16,
@@ -8942,7 +9427,7 @@ const bfd_target vms_alpha_vec =
   {_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_vms_lib_alpha_mkarchive, bfd_false},
   {bfd_false, alpha_vms_write_object_contents, /* bfd_write_contents.  */
    _bfd_vms_lib_write_archive_contents, bfd_false},
 
@@ -8958,5 +9443,5 @@ const bfd_target vms_alpha_vec =
 
   NULL,
 
-  (PTR) 0
+  NULL
 };
This page took 0.083488 seconds and 4 git commands to generate.