2010-08-04 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / vms-alpha.c
index 8d1d7cbf0886d044de7f9f641134118f7ba931e9..e500cd4d007514b021df3cac5952d9c253ab7f53 100644 (file)
    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)
    ...
 */
 
@@ -167,11 +168,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.  */
@@ -271,8 +272,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;
@@ -297,7 +304,6 @@ struct vms_private_data_struct
 
   struct module *modules;              /* list of all compilation units */
 
-  struct dst_info *dst_info;
   asection *dst_section;
 
   unsigned int dst_ptr_offsets_count;  /* # of offsets in following array  */
@@ -370,10 +376,10 @@ 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_fixup_lr (struct bfd_link_info *, unsigned int,
+                                    bfd_vma);
 static void alpha_vms_add_lw_reloc (struct bfd_link_info *info);
 static void alpha_vms_add_qw_reloc (struct bfd_link_info *info);
-static void alpha_vms_add_lw_fixup (struct bfd_link_info *, unsigned int,
-                                    bfd_vma);
 
 struct vector_type
 {
@@ -547,12 +553,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;
@@ -561,10 +569,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)
        {
@@ -665,12 +673,6 @@ _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);
@@ -680,12 +682,6 @@ _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset)
       if (_bfd_vms_slurp_object_records (abfd) != TRUE)
        return FALSE;
 
-      section->filepos = VMS_BLOCK_SIZE * (gstvbn - 1);
-      section->size = bfd_tell (abfd) - section->filepos;
-
-      if (!bfd_set_section_flags (abfd, section, bfd_flags))
-       return FALSE;
-
       abfd->flags |= HAS_SYMS;
     }
 
@@ -940,71 +936,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,
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
+      SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
     { EVAX_LITERAL_NAME,
-      (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD),
-      (SEC_DATA | SEC_READONLY),
-      (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD),
-      (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD,
+      SEC_DATA | SEC_READONLY,
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD,
+      SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD },
     { EVAX_LINK_NAME,
-      (EGPS__V_REL | EGPS__V_RD),
-      (SEC_DATA | SEC_READONLY),
-      (EGPS__V_REL | EGPS__V_RD),
-      (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+      EGPS__V_REL | EGPS__V_RD,
+      SEC_DATA | SEC_READONLY,
+      EGPS__V_REL | EGPS__V_RD,
+      SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD },
     { EVAX_DATA_NAME,
-      (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD),
-      (SEC_DATA),
-      (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
-      (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
+      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_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD },
     { EVAX_READONLY_NAME,
-      (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD),
-      (SEC_DATA | SEC_READONLY),
-      (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD),
-      (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD,
+      SEC_DATA | SEC_READONLY,
+      EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD,
+      SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD },
     { EVAX_LOCAL_NAME,
-      (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
-      (SEC_DATA),
-      (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
-      (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
+      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_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD },
     { NULL,
-      (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
-      (SEC_DATA),
-      (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT),
-      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
+      EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
+      SEC_DATA,
+      EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
+      SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }
   };
 
-/* Retrieve bfd section flags by name and size.  */
+/* 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;
@@ -1025,12 +1020,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;
 
@@ -1050,23 +1045,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)
@@ -1083,25 +1067,44 @@ 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;
   unsigned char *vms_rec;
-  flagword new_flags, old_flags;
-  char *name;
   unsigned long base_addr;
-  unsigned long align_addr;
 
   vms_debug2 ((2, "EGSD\n"));
 
@@ -1123,41 +1126,71 @@ _bfd_vms_slurp_egsd (bfd * abfd)
       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;
+            flagword new_flags, old_flags;
+            asection *section;
+
            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))
+
+            if ((old_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 = old_flags;
+                vms_section_data (section)->no_flags = 0;
+
+                new_flags = vms_secflag_by_name (evax_section_flags, name,
+                                                 section->size > 0);
+                if (!(old_flags & EGPS__V_NOMOD) && section->size > 0)
+                  {
+                    new_flags |= SEC_HAS_CONTENTS;
+                    if (old_flags & EGPS__V_REL)
+                      new_flags |= SEC_RELOC;
+                  }
+                if (!bfd_set_section_flags (abfd, section, new_flags))
+                  return FALSE;
+
+                /* 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;
 
@@ -1166,6 +1199,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)
@@ -1193,14 +1227,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)];
                   }
               }
          }
@@ -1208,15 +1243,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);
 
@@ -1229,7 +1260,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)
@@ -1237,7 +1272,7 @@ _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;
@@ -1602,7 +1637,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 ();
         }
     }
@@ -1617,16 +1653,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
@@ -1770,7 +1799,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)
@@ -1833,7 +1862,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);
                 }
             }
@@ -1857,7 +1886,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);
                     }
                 }
@@ -1967,9 +1996,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
@@ -2635,7 +2664,7 @@ _bfd_vms_write_eeom (bfd *abfd)
          return FALSE;
        }
       _bfd_vms_output_short (recwr, 0);
-      _bfd_vms_output_long (recwr, (unsigned long) (section->index));
+      _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);
@@ -2872,7 +2901,11 @@ alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
 
   if (sec->flags & SEC_CODE)
     eisd->u.eisd.flags |= EISD__M_EXE;
-  if (!(sec->flags & SEC_READONLY))
+  else if (!(sec->flags & SEC_READONLY))
+    eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
+
+  /* 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_LOAD))
@@ -2912,6 +2945,8 @@ alpha_vms_write_exec (bfd *abfd)
   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;
@@ -2940,7 +2975,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);
 
@@ -2958,11 +2992,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.  */
@@ -2976,6 +3009,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)
@@ -2984,8 +3018,15 @@ 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;
@@ -3085,6 +3126,7 @@ 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);
@@ -3092,9 +3134,17 @@ alpha_vms_write_exec (bfd *abfd)
 
       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.  */
@@ -3104,6 +3154,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;
 
@@ -3155,6 +3206,68 @@ alpha_vms_write_exec (bfd *abfd)
         }
     }
 
+  /* Write GST.  */
+  if (gst_filepos != 0)
+    {
+      struct vms_rec_wr *recwr = &PRIV (recwr);
+      unsigned int i;
+
+      _bfd_vms_write_emh (abfd);
+      _bfd_vms_write_lmn (abfd, "GNU LD");
+
+      /* 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);
+
+      for (i = 0; i < PRIV (gsd_sym_count); i++)
+        {
+          struct vms_symbol_entry *sym = PRIV (syms)[i];
+          char *hash;
+          bfd_vma val;
+          bfd_vma ep;
+
+          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);
+
+          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);
+          hash = _bfd_vms_length_hash_symbol (abfd, sym->name, EOBJ__C_SYMSIZ);
+          _bfd_vms_output_counted (recwr, hash);
+          _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);
+
+      if (!_bfd_vms_write_eeom (abfd))
+        return FALSE;
+    }
   return TRUE;
 }
 \f
@@ -3168,18 +3281,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);
@@ -3187,15 +3295,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)
@@ -3205,25 +3326,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;
@@ -3238,10 +3346,7 @@ _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))
@@ -3250,9 +3355,6 @@ _bfd_vms_write_egsd (bfd *abfd)
       else
        sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ__C_SECSIZ);
 
-      _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
-      _bfd_vms_output_short (recwr, section->alignment_power & 0xff);
-
       if (bfd_is_com_section (section))
        new_flags = (EGPS__V_OVR | EGPS__V_REL | EGPS__V_GBL | EGPS__V_RD
                     | EGPS__V_WRT | EGPS__V_NOMOD | EGPS__V_COM);
@@ -3271,14 +3373,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.  */
@@ -3291,30 +3396,56 @@ done:
       char *hash;
 
       symbol = abfd->outsymbols[symnum];
+      old_flags = symbol->flags;
+
+      /* Work-around a missing feature:  consider __main as the main entry
+         point.  */
       if (*(symbol->name) == '_')
        {
          if (strcmp (symbol->name, "__main") == 0)
            bfd_set_start_address (abfd, (bfd_vma)symbol->value);
        }
-      old_flags = symbol->flags;
 
+      /* 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.  */
@@ -3351,14 +3482,15 @@ 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);
@@ -3369,7 +3501,6 @@ done:
       _bfd_vms_output_counted (recwr, hash);
 
       _bfd_vms_output_end_subrec (recwr);
-
     }
 
   _bfd_vms_output_alignment (recwr, 8);
@@ -3469,8 +3600,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);
 
@@ -3494,7 +3624,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);
 
@@ -3599,7 +3729,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
   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))
@@ -3734,7 +3864,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
@@ -3787,7 +3918,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);
@@ -3830,11 +3962,13 @@ _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) udata->enbsym->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) udata->enbsym->section->target_index);
                  _bfd_vms_output_quad (recwr, rptr->addend);
                  _bfd_vms_output_counted
                    (recwr, _bfd_vms_length_hash_symbol
@@ -3855,11 +3989,12 @@ _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) udata->enbsym->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
@@ -3875,11 +4010,13 @@ _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) udata->enbsym->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) udata->enbsym->section->target_index);
                  _bfd_vms_output_quad (recwr, rptr->addend);
                  _bfd_vms_output_counted
                    (recwr, _bfd_vms_length_hash_symbol
@@ -4619,7 +4756,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
         {
@@ -4645,35 +4782,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:
@@ -5480,43 +5591,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);
@@ -6035,6 +6121,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;
@@ -7931,8 +8021,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)
 {
@@ -7945,8 +8038,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)
@@ -7962,25 +8058,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)
@@ -8443,10 +8533,82 @@ alpha_vms_build_fixups (struct bfd_link_info *info)
           bfd_putl32 (0, content + off + 4);
           off += 8;
         }
+    }
 
-      /* CA fixups.  */
+  return TRUE;
+}
+
+/* Called by bfd_link_hash_traverse to fill the symbol table.
+   Return FALSE in case of failure.  */
+
+static bfd_boolean
+alpha_vms_link_output_symbol (struct bfd_link_hash_entry *hc, void *infov)
+{
+  struct bfd_link_info *info = (struct bfd_link_info *)infov;
+  struct alpha_vms_link_hash_entry *h = (struct alpha_vms_link_hash_entry *)hc;
+  struct vms_symbol_entry *sym;
+
+  switch (h->root.type)
+    {
+    case bfd_link_hash_new:
+    case bfd_link_hash_undefined:
+      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:
+    case bfd_link_hash_warning:
+      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;
 }
 
@@ -8504,6 +8666,11 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
     }
 #endif
 
+  /* Generate the symbol table.  */
+  BFD_ASSERT (PRIV (syms) == NULL);
+  if (info->strip != strip_all)
+    bfd_link_hash_traverse (info->hash, alpha_vms_link_output_symbol, info);
+
   /* Find the entry point.  */
   if (bfd_get_start_address (abfd) == 0)
     {
@@ -8543,6 +8710,22 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
         }
     }
 
+  /* 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.  */
   base_addr = (bfd_vma)-1;
   last_addr = 0;
@@ -8576,11 +8759,13 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
   alpha_vms_link_hash (info)->base_addr = base_addr;
 
   /* Create the DMT section, if necessary.  */
-  dst = PRIV (dst_section);
+  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);
@@ -8820,7 +9005,7 @@ vms_close_and_cleanup (bfd * abfd)
         format.  */
       if (bfd_cache_close (abfd) != TRUE)
        return FALSE;
-      if (vms_convert_to_var_unix_filename (abfd->filename) != TRUE)
+      if (_bfd_vms_convert_to_var_unix_filename (abfd->filename) != TRUE)
        return FALSE;
     }
 #endif
@@ -8835,28 +9020,11 @@ 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));
+  vms_debug2 ((1, "vms_new_section_hook (%p, [%d]%s)\n",
+               abfd, section->index, section->name));
 
   bfd_set_section_alignment (abfd, section, 0);
 
-  if (section_count > PRIV (section_count))
-    {
-      amt = section_count;
-      amt *= sizeof (asection *);
-      PRIV (sections) = bfd_realloc_or_free (PRIV (sections), amt);
-      if (PRIV (sections) == NULL)
-       return FALSE;
-      PRIV (section_count) = section_count;
-    }
-
-  vms_debug2 ((6, "section_count: %d\n", PRIV (section_count)));
-
-  PRIV (sections)[section->index] = section;
-
   vms_debug2 ((7, "%d: %s\n", section->index, section->name));
 
   amt = sizeof (struct vms_section_data_struct);
@@ -8864,9 +9032,6 @@ vms_new_section_hook (bfd * abfd, asection *section)
   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);
 }
@@ -8934,7 +9099,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';
@@ -8944,14 +9109,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;
@@ -9123,7 +9289,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},
 
This page took 0.044448 seconds and 4 git commands to generate.