include/elf
authorTristan Gingold <gingold@adacore.com>
Fri, 11 Jun 2010 15:57:46 +0000 (15:57 +0000)
committerTristan Gingold <gingold@adacore.com>
Fri, 11 Jun 2010 15:57:46 +0000 (15:57 +0000)
2010-06-11  Tristan Gingold  <gingold@adacore.com>

* ia64.h (EF_IA_64_VMS_COMCOD, EF_IA_64_VMS_COMCOD_SUCCESS)
(EF_IA_64_VMS_COMCOD_WARNING, EF_IA_64_VMS_COMCOD_ERROR)
(EF_IA_64_VMS_COMCOD_ABORT, EF_IA_64_VMS_LINKAGES): Define.
(VMS_LF_CALL_DEBUG, VMS_LF_NOP0BUFS, VMS_LF_P0IMAGE)
(VMS_LF_MKTHREADS, VMS_LF_UPCALLS, VMS_LF_IMGSTA)
(VMS_LF_INITIALIZE, VMS_LF_MAIN, VMS_LF_EXE_INIT)
(VMS_LF_TBK_IN_IMG, VMS_LF_DBG_IN_IMG, VMS_LF_TBK_IN_DSF)
(VMS_LF_DBG_IN_DSF, VMS_LF_SIGNATURES, VMS_LF_REL_SEG_OFF): Define.
(VMS_STO_VISIBILITY, VMS_ST_VISIBILITY, VMS_STO_FUNC_TYPE)
(VMS_ST_FUNC_TYPE, VMS_SFT_CODE_ADDR, VMS_SFT_SYMV_IDX)
(VMS_SFT_FD, VMS_SFT_RESERVE, VMS_STO_LINKAGE, VMS_ST_LINKAGE)
(VMS_STL_IGNORE, VMS_STL_RESERVE, VMS_STL_STD, VMS_STL_LNK): Define.
(Elf64_External_VMS_IMAGE_FIXUP): New declaration.
(Elf64_External_VMS_IMAGE_RELA): Ditto.
(R_IA64_VMS_DIR8, R_IA64_VMS_DIR16LSB, R_IA64_VMS_CALL_SIGNATURE)
(R_IA64_VMS_EXECLET_FUNC, R_IA64_VMS_EXECLET_DATA, R_IA64_VMS_FIX8)
(R_IA64_VMS_FIX16, R_IA64_VMS_FIX32, R_IA64_VMS_FIX64)
(R_IA64_VMS_FIXFD, R_IA64_VMS_ACC_LOAD, R_IA64_VMS_ACC_ADD)
(R_IA64_VMS_ACC_SUB, R_IA64_VMS_ACC_MUL, R_IA64_VMS_ACC_DIV)
(R_IA64_VMS_ACC_AND, R_IA64_VMS_ACC_IOR, R_IA64_VMS_ACC_EOR)
(R_IA64_VMS_ACC_ASH, R_IA64_VMS_ACC_STO8, R_IA64_VMS_ACC_STO16LSH)
(R_IA64_VMS_ACC_STO32LSH, R_IA64_VMS_ACC_STO64LSH): New.

binutils/
2010-06-11  Tristan Gingold  <gingold@adacore.com>
    Doug Rupp <rupp@gnat.com>

* readelf.c (is_ia64_vms): New function.
(dump_relocations): Use it.
(get_machine_flags): Display IA-64 OpenVMS flags.
(process_program_headers): No error on OpenVMS if no .dynamic section.
(struct ia64_vms_dynfixup, struct ia64_vms_dynimgrela): New
declarations.
(dump_ia64_vms_dynamic_fixups): New function.
(dump_ia64_vms_dynamic_relocs): Ditto.
(process_ia64_vms_dynamic_relocs): Ditto.
(process_relocs): Handle IA-64 OpenVMS relocs.
(VMS_EPOCH_OFFSET, VMS_GRANULARITY_FACTOR): New macros.
(print_vms_time): New function.
(dynamic_section_ia64_val): Handle DT_IA_64_VMS_LINKTIME and
DT_IA_64_VMS_LNKFLAGS.
(get_ia64_symbol_other): New function.
(get_symbol_other): Handle EM_IA_64.

binutils/ChangeLog
binutils/readelf.c
include/elf/ChangeLog
include/elf/ia64.h

index 583c9d61cf636db0e1b421d2a65900913db3ef2d..72745ad0065e0ff163736decc52e791f00499313 100644 (file)
@@ -1,3 +1,23 @@
+2010-06-11  Tristan Gingold  <gingold@adacore.com>
+           Doug Rupp <rupp@gnat.com>
+
+       * readelf.c (is_ia64_vms): New function.
+       (dump_relocations): Use it.
+       (get_machine_flags): Display IA-64 OpenVMS flags.
+       (process_program_headers): No error on OpenVMS if no .dynamic section.
+       (struct ia64_vms_dynfixup, struct ia64_vms_dynimgrela): New
+       declarations.
+       (dump_ia64_vms_dynamic_fixups): New function.
+       (dump_ia64_vms_dynamic_relocs): Ditto.
+       (process_ia64_vms_dynamic_relocs): Ditto.
+       (process_relocs): Handle IA-64 OpenVMS relocs.
+       (VMS_EPOCH_OFFSET, VMS_GRANULARITY_FACTOR): New macros.
+       (print_vms_time): New function.
+       (dynamic_section_ia64_val): Handle DT_IA_64_VMS_LINKTIME and
+       DT_IA_64_VMS_LNKFLAGS.
+       (get_ia64_symbol_other): New function.
+       (get_symbol_other): Handle EM_IA_64.
+
 2010-06-11  Tristan Gingold  <gingold@adacore.com>
 
        * unwind-ia64.c (unw_print_abreg): Add const to special_reg.
index 2ea1bf7a70fefbb738fa466d0b0bee7384c2904b..757fefbdd4d6bdd4b9d50e5911a7c7b0b60b39fa 100644 (file)
@@ -577,6 +577,17 @@ read_uleb128 (unsigned char *data, unsigned int *length_return)
   return read_leb128 (data, length_return, 0);
 }
 
+/* Return true if the current file is for IA-64 machine and OpenVMS ABI.
+   This OS has so many departures from the ELF standard that we test it at
+   many places.  */
+
+static inline int
+is_ia64_vms (void)
+{
+  return elf_header.e_machine == EM_IA_64
+    && elf_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS;
+}
+
 /* Guess the relocation size commonly used by the specific machines.  */
 
 static int
@@ -1372,9 +1383,7 @@ dump_relocations (FILE * file,
                               && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
                               && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
                        sec_name = "ANSI_COM";
-                     else if (elf_header.e_machine == EM_IA_64
-                              && (elf_header.e_ident[EI_OSABI]
-                                  == ELFOSABI_OPENVMS)
+                     else if (is_ia64_vms ()
                               && psym->st_shndx == SHN_IA_64_VMS_SYMVEC)
                        sec_name = "VMS_SYMVEC";
                      else
@@ -2553,6 +2562,27 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            strcat (buf, ", constant gp");
          if ((e_flags & EF_IA_64_ABSOLUTE))
            strcat (buf, ", absolute");
+          if (elf_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS)
+            {
+              if ((e_flags & EF_IA_64_VMS_LINKAGES))
+                strcat (buf, ", vms_linkages");
+              switch ((e_flags & EF_IA_64_VMS_COMCOD))
+                {
+                case EF_IA_64_VMS_COMCOD_SUCCESS:
+                  break;
+                case EF_IA_64_VMS_COMCOD_WARNING:
+                  strcat (buf, ", warning");
+                  break;
+                case EF_IA_64_VMS_COMCOD_ERROR:
+                  strcat (buf, ", error");
+                  break;
+                case EF_IA_64_VMS_COMCOD_ABORT:
+                  strcat (buf, ", abort");
+                  break;
+                default:
+                  abort ();
+                }
+            }
          break;
 
        case EM_VAX:
@@ -3789,7 +3819,10 @@ process_program_headers (FILE * file)
              sec = find_section (".dynamic");
              if (sec == NULL || sec->sh_size == 0)
                {
-                 error (_("no .dynamic section in the dynamic segment\n"));
+                  /* A corresponding .dynamic section is expected, but on
+                     IA-64/OpenVMS it is OK for it to be missing.  */
+                  if (!is_ia64_vms ())
+                    error (_("no .dynamic section in the dynamic segment\n"));
                  break;
                }
 
@@ -5038,6 +5071,187 @@ process_section_groups (FILE * file)
   return 1;
 }
 
+/* Data used to display dynamic fixups.  */
+
+struct ia64_vms_dynfixup
+{
+  bfd_vma needed_ident;                /* Library ident number.  */
+  bfd_vma needed;              /* Index in the dstrtab of the library name.  */
+  bfd_vma fixup_needed;                /* Index of the library.  */
+  bfd_vma fixup_rela_cnt;      /* Number of fixups.  */
+  bfd_vma fixup_rela_off;      /* Fixups offset in the dynamic segment.  */
+};
+
+/* Data used to display dynamic relocations.  */
+
+struct ia64_vms_dynimgrela
+{
+  bfd_vma img_rela_cnt;                /* Number of relocations.  */
+  bfd_vma img_rela_off;                /* Reloc offset in the dynamic segment.  */
+};
+
+/* Display IA-64 OpenVMS dynamic fixups (used to dynamically link a shared
+   library).  */
+
+static void
+dump_ia64_vms_dynamic_fixups (FILE *file, struct ia64_vms_dynfixup *fixup,
+                              const char *strtab, unsigned int strtab_sz)
+{
+  Elf64_External_VMS_IMAGE_FIXUP *imfs;
+  long i;
+  const char *lib_name;
+
+  imfs = get_data (NULL, file, dynamic_addr + fixup->fixup_rela_off,
+                  1, fixup->fixup_rela_cnt * sizeof (*imfs),
+                  _("dynamic section image fixups"));
+  if (!imfs)
+    return;
+
+  if (fixup->needed < strtab_sz)
+    lib_name = strtab + fixup->needed;
+  else
+    {
+      warn ("corrupt library name index of 0x%lx found in dynamic entry",
+            fixup->needed);
+      lib_name = "???";
+    }
+  printf (_("\nImage fixups for needed library #%d: %s - ident: %lx\n"),
+         (int) fixup->fixup_needed, lib_name, (long) fixup->needed_ident);
+  printf
+    (_("Seg Offset           Type                             SymVec DataType\n"));
+
+  for (i = 0; i < (long) fixup->fixup_rela_cnt; i++)
+    {
+      unsigned int type;
+      const char *rtype;
+
+      printf ("%3u ", (unsigned) BYTE_GET (imfs [i].fixup_seg));
+      printf_vma ((bfd_vma) BYTE_GET (imfs [i].fixup_offset));
+      type = BYTE_GET (imfs [i].type);
+      rtype = elf_ia64_reloc_type (type);
+      if (rtype == NULL)
+        printf (" 0x%08x                       ", type);
+      else
+        printf (" %-32s ", rtype);
+      printf ("%6u ", (unsigned) BYTE_GET (imfs [i].symvec_index));
+      printf ("0x%08x\n", (unsigned) BYTE_GET (imfs [i].data_type));
+    }
+
+  free (imfs);
+}
+
+/* Display IA-64 OpenVMS dynamic relocations (used to relocate an image).  */
+
+static void
+dump_ia64_vms_dynamic_relocs (FILE *file, struct ia64_vms_dynimgrela *imgrela)
+{
+  Elf64_External_VMS_IMAGE_RELA *imrs;
+  long i;
+
+  imrs = get_data (NULL, file, dynamic_addr + imgrela->img_rela_off,
+                  1, imgrela->img_rela_cnt * sizeof (*imrs),
+                  _("dynamic section image relas"));
+  if (!imrs)
+    return;
+
+  printf (_("\nImage relocs\n"));
+  printf
+    (_("Seg Offset   Type                            Addend            Seg Sym Off\n"));
+
+  for (i = 0; i < (long) imgrela->img_rela_cnt; i++)
+    {
+      unsigned int type;
+      const char *rtype;
+
+      printf ("%3u ", (unsigned) BYTE_GET (imrs [i].rela_seg));
+      printf ("%08" BFD_VMA_FMT "x ",
+              (bfd_vma) BYTE_GET (imrs [i].rela_offset));
+      type = BYTE_GET (imrs [i].type);
+      rtype = elf_ia64_reloc_type (type);
+      if (rtype == NULL)
+        printf ("0x%08x                      ", type);
+      else
+        printf ("%-31s ", rtype);
+      print_vma (BYTE_GET (imrs [i].addend), FULL_HEX);
+      printf ("%3u ", (unsigned) BYTE_GET (imrs [i].sym_seg));
+      printf ("%08" BFD_VMA_FMT "x\n",
+              (bfd_vma) BYTE_GET (imrs [i].sym_offset));
+    }
+
+  free (imrs);
+}
+
+/* Display IA-64 OpenVMS dynamic relocations and fixups.  */
+
+static int
+process_ia64_vms_dynamic_relocs (FILE *file)
+{
+  struct ia64_vms_dynfixup fixup;
+  struct ia64_vms_dynimgrela imgrela;
+  Elf_Internal_Dyn *entry;
+  int res = 0;
+  bfd_vma strtab_off = 0;
+  bfd_vma strtab_sz = 0;
+  char *strtab = NULL;
+
+  memset (&fixup, 0, sizeof (fixup));
+  memset (&imgrela, 0, sizeof (imgrela));
+
+  /* Note: the order of the entries is specified by the OpenVMS specs.  */
+  for (entry = dynamic_section;
+       entry < dynamic_section + dynamic_nent;
+       entry++)
+    {
+      switch (entry->d_tag)
+        {
+        case DT_IA_64_VMS_STRTAB_OFFSET:
+          strtab_off = entry->d_un.d_val;
+          break;
+        case DT_STRSZ:
+          strtab_sz = entry->d_un.d_val;
+          if (strtab == NULL)
+            strtab = get_data (NULL, file, dynamic_addr + strtab_off,
+                               1, strtab_sz, _("dynamic string section"));
+          break;
+
+        case DT_IA_64_VMS_NEEDED_IDENT:
+          fixup.needed_ident = entry->d_un.d_val;
+          break;
+        case DT_NEEDED:
+          fixup.needed = entry->d_un.d_val;
+          break;
+        case DT_IA_64_VMS_FIXUP_NEEDED:
+          fixup.fixup_needed = entry->d_un.d_val;
+          break;
+        case DT_IA_64_VMS_FIXUP_RELA_CNT:
+          fixup.fixup_rela_cnt = entry->d_un.d_val;
+          break;
+        case DT_IA_64_VMS_FIXUP_RELA_OFF:
+          fixup.fixup_rela_off = entry->d_un.d_val;
+          res++;
+          dump_ia64_vms_dynamic_fixups (file, &fixup, strtab, strtab_sz);
+          break;
+
+        case DT_IA_64_VMS_IMG_RELA_CNT:
+         imgrela.img_rela_cnt = entry->d_un.d_val;
+          break;
+        case DT_IA_64_VMS_IMG_RELA_OFF:
+         imgrela.img_rela_off = entry->d_un.d_val;
+          res++;
+          dump_ia64_vms_dynamic_relocs (file, &imgrela);
+          break;
+
+        default:
+          break;
+       }
+    }
+
+  if (strtab != NULL)
+    free (strtab);
+
+  return res;
+}
+
 static struct
 {
   const char * name;
@@ -5109,6 +5323,9 @@ process_relocs (FILE * file)
            }
        }
 
+      if (is_ia64_vms ())
+        has_dynamic_reloc |= process_ia64_vms_dynamic_relocs (file);
+
       if (! has_dynamic_reloc)
        printf (_("\nThere are no dynamic relocations in this file.\n"));
     }
@@ -6667,6 +6884,29 @@ dynamic_section_parisc_val (Elf_Internal_Dyn * entry)
   putchar ('\n');
 }
 
+#ifdef BFD64
+
+/* VMS vs Unix time offset and factor.  */
+
+#define VMS_EPOCH_OFFSET 35067168000000000LL
+#define VMS_GRANULARITY_FACTOR 10000000
+
+/* Display a VMS time in a human readable format.  */
+
+static void
+print_vms_time (bfd_int64_t vmstime)
+{
+  struct tm *tm;
+  time_t unxtime;
+
+  unxtime = (vmstime - VMS_EPOCH_OFFSET) / VMS_GRANULARITY_FACTOR;
+  tm = gmtime (&unxtime);
+  printf ("%04u-%02u-%02uT%02u:%02u:%02u",
+          tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+          tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+#endif /* BFD64 */
+
 static void
 dynamic_section_ia64_val (Elf_Internal_Dyn * entry)
 {
@@ -6679,6 +6919,46 @@ dynamic_section_ia64_val (Elf_Internal_Dyn * entry)
       print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX);
       break;
 
+    case DT_IA_64_VMS_LINKTIME:
+#ifdef BFD64
+      print_vms_time (entry->d_un.d_val);
+#endif
+      break;
+
+    case DT_IA_64_VMS_LNKFLAGS:
+      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+      if (entry->d_un.d_val & VMS_LF_CALL_DEBUG)
+        printf (" CALL_DEBUG");
+      if (entry->d_un.d_val & VMS_LF_NOP0BUFS)
+        printf (" NOP0BUFS");
+      if (entry->d_un.d_val & VMS_LF_P0IMAGE)
+        printf (" P0IMAGE");
+      if (entry->d_un.d_val & VMS_LF_MKTHREADS)
+        printf (" MKTHREADS");
+      if (entry->d_un.d_val & VMS_LF_UPCALLS)
+        printf (" UPCALLS");
+      if (entry->d_un.d_val & VMS_LF_IMGSTA)
+        printf (" IMGSTA");
+      if (entry->d_un.d_val & VMS_LF_INITIALIZE)
+        printf (" INITIALIZE");
+      if (entry->d_un.d_val & VMS_LF_MAIN)
+        printf (" MAIN");
+      if (entry->d_un.d_val & VMS_LF_EXE_INIT)
+        printf (" EXE_INIT");
+      if (entry->d_un.d_val & VMS_LF_TBK_IN_IMG)
+        printf (" TBK_IN_IMG");
+      if (entry->d_un.d_val & VMS_LF_DBG_IN_IMG)
+        printf (" DBG_IN_IMG");
+      if (entry->d_un.d_val & VMS_LF_TBK_IN_DSF)
+        printf (" TBK_IN_DSF");
+      if (entry->d_un.d_val & VMS_LF_DBG_IN_DSF)
+        printf (" DBG_IN_DSF");
+      if (entry->d_un.d_val & VMS_LF_SIGNATURES)
+        printf (" SIGNATURES");
+      if (entry->d_un.d_val & VMS_LF_REL_SEG_OFF)
+        printf (" REL_SEG_OFF");
+      break;
+
     default:
       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
       break;
@@ -7972,6 +8252,67 @@ get_mips_symbol_other (unsigned int other)
     }
 }
 
+static const char *
+get_ia64_symbol_other (unsigned int other)
+{
+  if (is_ia64_vms ())
+    {
+      static char res[32];
+
+      res[0] = 0;
+
+      /* Function types is for images and .STB files only.  */
+      switch (elf_header.e_type)
+        {
+        case ET_DYN:
+        case ET_EXEC:
+          switch (VMS_ST_FUNC_TYPE (other))
+            {
+            case VMS_SFT_CODE_ADDR:
+              strcat (res, " CA");
+              break;
+            case VMS_SFT_SYMV_IDX:
+              strcat (res, " VEC");
+              break;
+            case VMS_SFT_FD:
+              strcat (res, " FD");
+              break;
+            case VMS_SFT_RESERVE:
+              strcat (res, " RSV");
+              break;
+            default:
+              abort ();
+            }
+          break;
+        default:
+          break;
+        }
+      switch (VMS_ST_LINKAGE (other))
+        {
+        case VMS_STL_IGNORE:
+          strcat (res, " IGN");
+          break;
+        case VMS_STL_RESERVE:
+          strcat (res, " RSV");
+          break;
+        case VMS_STL_STD:
+          strcat (res, " STD");
+          break;
+        case VMS_STL_LNK:
+          strcat (res, " LNK");
+          break;
+        default:
+          abort ();
+        }
+
+      if (res[0] != 0)
+        return res + 1;
+      else
+        return res;
+    }
+  return NULL;
+}
+
 static const char *
 get_symbol_other (unsigned int other)
 {
@@ -7985,6 +8326,10 @@ get_symbol_other (unsigned int other)
     {
     case EM_MIPS:
       result = get_mips_symbol_other (other);
+      break;
+    case EM_IA_64:
+      result = get_ia64_symbol_other (other);
+      break;
     default:
       break;
     }
index ddd927ae805f26ee15d9e52d1809505594e3d34a..bf36e1e1d1dd8f0ba08cb04513b7e3e49ba7ba6f 100644 (file)
@@ -1,3 +1,28 @@
+2010-06-11  Tristan Gingold  <gingold@adacore.com>
+
+       * ia64.h (EF_IA_64_VMS_COMCOD, EF_IA_64_VMS_COMCOD_SUCCESS)
+       (EF_IA_64_VMS_COMCOD_WARNING, EF_IA_64_VMS_COMCOD_ERROR)
+       (EF_IA_64_VMS_COMCOD_ABORT, EF_IA_64_VMS_LINKAGES): Define.
+       (VMS_LF_CALL_DEBUG, VMS_LF_NOP0BUFS, VMS_LF_P0IMAGE)
+       (VMS_LF_MKTHREADS, VMS_LF_UPCALLS, VMS_LF_IMGSTA)
+       (VMS_LF_INITIALIZE, VMS_LF_MAIN, VMS_LF_EXE_INIT)
+       (VMS_LF_TBK_IN_IMG, VMS_LF_DBG_IN_IMG, VMS_LF_TBK_IN_DSF)
+       (VMS_LF_DBG_IN_DSF, VMS_LF_SIGNATURES, VMS_LF_REL_SEG_OFF): Define.
+       (VMS_STO_VISIBILITY, VMS_ST_VISIBILITY, VMS_STO_FUNC_TYPE)
+       (VMS_ST_FUNC_TYPE, VMS_SFT_CODE_ADDR, VMS_SFT_SYMV_IDX)
+       (VMS_SFT_FD, VMS_SFT_RESERVE, VMS_STO_LINKAGE, VMS_ST_LINKAGE)
+       (VMS_STL_IGNORE, VMS_STL_RESERVE, VMS_STL_STD, VMS_STL_LNK): Define.
+       (Elf64_External_VMS_IMAGE_FIXUP): New declaration.
+       (Elf64_External_VMS_IMAGE_RELA): Ditto.
+       (R_IA64_VMS_DIR8, R_IA64_VMS_DIR16LSB, R_IA64_VMS_CALL_SIGNATURE)
+       (R_IA64_VMS_EXECLET_FUNC, R_IA64_VMS_EXECLET_DATA, R_IA64_VMS_FIX8)
+       (R_IA64_VMS_FIX16, R_IA64_VMS_FIX32, R_IA64_VMS_FIX64)
+       (R_IA64_VMS_FIXFD, R_IA64_VMS_ACC_LOAD, R_IA64_VMS_ACC_ADD)
+       (R_IA64_VMS_ACC_SUB, R_IA64_VMS_ACC_MUL, R_IA64_VMS_ACC_DIV)
+       (R_IA64_VMS_ACC_AND, R_IA64_VMS_ACC_IOR, R_IA64_VMS_ACC_EOR)
+       (R_IA64_VMS_ACC_ASH, R_IA64_VMS_ACC_STO8, R_IA64_VMS_ACC_STO16LSH)
+       (R_IA64_VMS_ACC_STO32LSH, R_IA64_VMS_ACC_STO64LSH): New.
+
 2010-05-25  Daniel Jacobowitz  <dan@codesourcery.com>
            Joseph Myers  <joseph@codesourcery.com>
            Andrew Stubbs  <ams@codesourcery.com>
index 625933caa8c21a859fb57b5768489e696bd60740..fb3d99f4008db54d316c13823bac1439c1e3f34f 100644 (file)
 /* Not used yet.  */
 #define EF_IA_64_ABSOLUTE          (1 << 8) /* Load at absolute addresses.  */
 
+/* OpenVMS speficic.  */
+#define EF_IA_64_VMS_COMCOD        0x03   /* Completion code.  */
+#define EF_IA_64_VMS_COMCOD_SUCCESS 0
+#define EF_IA_64_VMS_COMCOD_WARNING 1
+#define EF_IA_64_VMS_COMCOD_ERROR   2
+#define EF_IA_64_VMS_COMCOD_ABORT   3
+#define EF_IA_64_VMS_LINKAGES      0x04   /* Contains VMS linkages info.  */
+
 #define ELF_STRING_ia64_archext                ".IA_64.archext"
 #define ELF_STRING_ia64_pltoff         ".IA_64.pltoff"
 #define ELF_STRING_ia64_unwind         ".IA_64.unwind"
 #define DT_IA_64_VMS_PLTGOT_SEG      (DT_LOOS + 64)
 #define DT_IA_64_VMS_FPMODE          (DT_LOOS + 66)
 
+/* Values for DT_IA_64_LNKFLAGS.  */
+#define VMS_LF_CALL_DEBUG      0x0001  /* Activate and call the debugger.  */
+#define VMS_LF_NOP0BUFS                0x0002  /* RMS use of P0 for i/o disabled.  */
+#define VMS_LF_P0IMAGE         0x0004  /* Image in P0 space only.  */
+#define VMS_LF_MKTHREADS       0x0008  /* Multiple kernel threads enabled.  */
+#define VMS_LF_UPCALLS         0x0010  /* Upcalls enabled.  */
+#define VMS_LF_IMGSTA          0x0020  /* Use SYS$IMGSTA.  */
+#define VMS_LF_INITIALIZE      0x0040  /* Image uses tfradr2.  */
+#define VMS_LF_MAIN            0x0080  /* Image uses tfradr3.  */
+#define VMS_LF_EXE_INIT                0x0200  /* Image uses tfradr4.  */
+#define VMS_LF_TBK_IN_IMG      0x0400  /* Traceback records in image.  */
+#define VMS_LF_DBG_IN_IMG      0x0800  /* Debug records in image.  */
+#define VMS_LF_TBK_IN_DSF      0x1000  /* Traceback records in DSF.  */
+#define VMS_LF_DBG_IN_DSF      0x2000  /* Debug records in DSF.  */
+#define VMS_LF_SIGNATURES      0x4000  /* Signatures present.  */
+#define VMS_LF_REL_SEG_OFF     0x8000  /* Maintain relative pos of seg.  */
+
 /* This section only used by HP-UX, The HP linker gives weak symbols
    precedence over regular common symbols.  We want common to override
    weak.  Using this common instead of SHN_COMMON does that.  */
    vector (only possible for image files).  */
 #define SHN_IA_64_VMS_SYMVEC SHN_LOOS
 
+/* OpenVMS IA64-specific symbol attributes.  */
+#define VMS_STO_VISIBILITY 3     /* Alias of the standard field.  */
+#define VMS_ST_VISIBILITY(o) ((o) & VMS_STO_VISIBILITY)
+#define VMS_STO_FUNC_TYPE  0x30          /* Function type.  */
+#define VMS_ST_FUNC_TYPE(o)  (((o) & VMS_STO_FUNC_TYPE) >> 4)
+# define VMS_SFT_CODE_ADDR 0     /* Symbol value is a code address.  */
+# define VMS_SFT_SYMV_IDX  1     /* Symbol value is a symbol vector index.  */
+# define VMS_SFT_FD       2      /* Symbol value is a function descriptor.  */
+# define VMS_SFT_RESERVE   3     /* Reserved.  */
+#define VMS_STO_LINKAGE    0xc0
+#define VMS_ST_LINKAGE(o)  (((o) & VMS_STO_LINKAGE) >> 6)
+# define VMS_STL_IGNORE           0      /* No associated linkage.  */
+# define VMS_STL_RESERVE   1
+# define VMS_STL_STD      2      /* Standard linkage with return value.  */
+# define VMS_STL_LNK      3      /* Explicit represented in .vms_linkages.  */
+
+/* OpenVMS specific fixup and relocation structures.  */
+
+typedef struct
+{
+  unsigned char fixup_offset[8];
+  unsigned char type[4];
+  unsigned char fixup_seg[4];
+  unsigned char addend[8];
+  unsigned char symvec_index[4];
+  unsigned char data_type[4];
+} Elf64_External_VMS_IMAGE_FIXUP;
+
+typedef struct
+{
+  unsigned char rela_offset[8];
+  unsigned char type[4];
+  unsigned char rela_seg[4];
+  unsigned char addend[8];
+  unsigned char sym_offset[8];
+  unsigned char sym_seg[4];
+  unsigned char fill_1[4];
+} Elf64_External_VMS_IMAGE_RELA;
+
 /* IA64-specific relocation types: */
 
 /* Relocs apply to specific instructions within a bundle.  The least
@@ -282,6 +346,31 @@ START_RELOC_NUMBERS (elf_ia64_reloc_type)
   RELOC_NUMBER (R_IA64_LTOFF_DTPREL22, 0xba) /* @ltoff(@dtprel(s+a)), imm22 */
 
   FAKE_RELOC (R_IA64_MAX_RELOC_CODE, 0xba)
+
+  /* OpenVMS specific relocs.  */
+  RELOC_NUMBER (R_IA64_VMS_DIR8, 0x70000000)           /* S + A */
+  RELOC_NUMBER (R_IA64_VMS_DIR16LSB, 0x70000001)       /* S + A */
+  RELOC_NUMBER (R_IA64_VMS_CALL_SIGNATURE, 0x70000002)
+  RELOC_NUMBER (R_IA64_VMS_EXECLET_FUNC, 0x70000003)
+  RELOC_NUMBER (R_IA64_VMS_EXECLET_DATA, 0x70000004)
+  RELOC_NUMBER (R_IA64_VMS_FIX8, 0x70000005)           /* S + A */
+  RELOC_NUMBER (R_IA64_VMS_FIX16, 0x70000006)          /* S + A */
+  RELOC_NUMBER (R_IA64_VMS_FIX32, 0x70000007)          /* S + A */
+  RELOC_NUMBER (R_IA64_VMS_FIX64, 0x70000008)          /* S + A */
+  RELOC_NUMBER (R_IA64_VMS_FIXFD, 0x70000009)
+  RELOC_NUMBER (R_IA64_VMS_ACC_LOAD, 0x7000000a)       /* ACC = S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_ADD, 0x7000000b)                /* ACC += S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_SUB, 0x7000000c)                /* ACC -= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_MUL, 0x7000000d)                /* ACC *= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_DIV, 0x7000000e)                /* ACC /= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_AND, 0x7000000f)                /* ACC &= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_IOR, 0x70000010)                /* ACC |= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_EOR, 0x70000011)                /* ACC ^= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_ASH, 0x70000012)                /* ACC >>= S + A */
+  RELOC_NUMBER (R_IA64_VMS_ACC_STO8, 0x70000014)       /* ACC */
+  RELOC_NUMBER (R_IA64_VMS_ACC_STO16LSH, 0x70000015)   /* ACC */
+  RELOC_NUMBER (R_IA64_VMS_ACC_STO32LSH, 0x70000016)   /* ACC */
+  RELOC_NUMBER (R_IA64_VMS_ACC_STO64LSH, 0x70000017)   /* ACC */
 END_RELOC_NUMBERS (R_IA64_max)
 
 #endif /* _ELF_IA64_H */