bfd/
authorTristan Gingold <gingold@adacore.com>
Fri, 30 Apr 2010 09:40:42 +0000 (09:40 +0000)
committerTristan Gingold <gingold@adacore.com>
Fri, 30 Apr 2010 09:40:42 +0000 (09:40 +0000)
2010-04-30  Tristan Gingold  <gingold@adacore.com>

* vms-lib.c (struct lib_tdata): Field artdata added, fields nbr_syms
and syms removed.
(struct carsym_mem): New structure.
(vms_add_index): New function.
(vms_add_indexes_from_list): New function.
(vms_traverse_index): Parameter carsym changed to carsym_mem.
Code adjusted to handle elfidx.
(vms_lib_read_index): Adjusted for vms_traverse_index changes.
Parameter NBREL is now a pointer.
(_bfd_vms_lib_archive_p): Adjust for above change.  Handle ia64
archives.
(_bfd_vms_lib_mkarchive): Adjusted for changes in struct lib_tdata.
(_bfd_vms_lib_find_symbol): Ditto.
(vms_lib_bopen): Fix two typos: return FALSE in case of error,
check MHD id.
* vms-alpha.c (alpha_vms_link_add_archive_symbols): Adjust for
changes of _bfd_vms_lib_find_symbol.

include/vms
2010-04-30  Tristan Gingold  <gingold@adacore.com>

* lbr.h (LBR__C_TYP_ISHSTB): Added.
(LHD_SANEID4): Renamed to ...
(LHD_SANEID6): ...  this.
(LBR_MAJORID, LBR_ELFMAJORID): New macros.
(struct vms_rfa): New structure.
(struct vms_idxdef): Renamed to ...
(struct vms_idx): ... this.
(struct vms_idxdef2): Renamed to ...
(struct vms_elfidx): ... this.
(ELFIDX__WEAK, ELFIDX__GROUP, ELFIDX__LISTRFA, ELFIDX__SYMESC): New
macros.
(struct vms_lhs, struct vms_lns): New structures.
(struct vms_mhd): Add missing fields.
(MHD__C_MHDLEN): New macro.

bfd/ChangeLog
bfd/vms-alpha.c
bfd/vms-lib.c
include/vms/ChangeLog
include/vms/lbr.h

index 19306b2..a66fc32 100644 (file)
@@ -1,3 +1,29 @@
+2010-04-30  Tristan Gingold  <gingold@adacore.com>
+
+       * vms-lib.c (struct lib_tdata): Field artdata added, fields nbr_syms
+       and syms removed.
+       (struct carsym_mem): New structure.
+       (vms_add_index): New function.
+       (vms_add_indexes_from_list): New function.
+       (vms_traverse_index): Parameter carsym changed to carsym_mem.
+       Code adjusted to handle elfidx.
+       (vms_lib_read_index): Adjusted for vms_traverse_index changes.
+       Parameter NBREL is now a pointer.
+       (_bfd_vms_lib_archive_p): Adjust for above change.  Handle ia64
+       archives.
+       (_bfd_vms_lib_mkarchive): Adjusted for changes in struct lib_tdata.
+       (_bfd_vms_lib_find_symbol): Ditto.
+       (vms_lib_bopen): Fix two typos: return FALSE in case of error,
+       check MHD id.
+       (_bfd_vms_lib_get_module): New function.
+       (_bfd_vms_lib_get_elt_at_index): Rewritten using the above
+       function.
+       (_bfd_vms_lib_openr_next_archived_file): Use _bfd_vms_lib_get_module.
+       (_bfd_vms_lib_generic_stat_arch_elt): Handle ia64 archives.
+       (vms_write_index): Adjust for structure renamed.
+       * vms-alpha.c (alpha_vms_link_add_archive_symbols): Adjust for
+       changes of _bfd_vms_lib_find_symbol.
+
 2010-04-28  Kai Tietz  <kai.tietz@onevision.com>
 
        * config.bfd: Correct accidential reverted patch
index 3013192..294bd90 100644 (file)
@@ -8040,7 +8040,7 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
   for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef)
     {
       struct bfd_link_hash_entry *h;
-      file_ptr file_offset;
+      symindex symidx;
       bfd *element;
       bfd *orig_element;
 
@@ -8066,14 +8066,14 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
        }
 
       /* Look for this symbol in the archive hash table.  */
-      file_offset = _bfd_vms_lib_find_symbol (abfd, h->root.string);
-      if (file_offset == 0)
+      symidx = _bfd_vms_lib_find_symbol (abfd, h->root.string);
+      if (symidx == BFD_NO_MORE_SYMBOLS)
        {
          /* Nothing in this slot.  */
          continue;
        }
 
-      element = bfd_get_elt_at_index (abfd, file_offset);
+      element = bfd_get_elt_at_index (abfd, symidx);
       if (element == NULL)
        return FALSE;
 
index d05fab7..fcfdf0f 100644 (file)
@@ -62,6 +62,9 @@ enum vms_lib_kind
 
 struct lib_tdata
 {
+  /* Standard tdata for an archive.  But we don't use many fields.  */
+  struct artdata artdata;
+
   /* Major version.  */
   unsigned char ver;
 
@@ -79,10 +82,6 @@ struct lib_tdata
   struct carsym *modules;
   bfd **cache;
 
-  /* Vector of symbols (archive map), already sorted.  */
-  unsigned int nbr_syms;
-  struct carsym *syms;
-
   /* DCX (decompression) data.  */
   unsigned int nbr_dcxsbm;
   struct dcxsbm_desc *dcxsbm;
@@ -94,16 +93,109 @@ struct lib_tdata
 
 static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
 
+/* Describe the current state of carsym entries while building the archive
+   table of content.  Things are simple with Alpha archives as the number
+   of entries is known, but with IA64 archives a entry can make a reference
+   to severals members.  Therefore we must be able to extend the table on the
+   fly, but it should be allocated on the bfd - which doesn't support realloc.
+   To reduce the overhead, the table is initially allocated in the BFD's
+   objalloc and extended if necessary on the heap.  In the later case, it
+   is finally copied to the BFD's objalloc so that it will automatically be
+   freed.  */
+
+struct carsym_mem
+{
+  /* The table of content.  */
+  struct carsym *idx;
+
+  /* Number of entries used in the table.  */
+  unsigned int nbr;
+
+  /* Maximum number of entries.  */
+  unsigned int max;
+
+  /* If true, the table was reallocated on the heap.  If false, it is still
+     in the BFD's objalloc.  */
+  bfd_boolean realloced;
+};
+
+/* Simply add a name to the index.  */
+
+static bfd_boolean
+vms_add_index (struct carsym_mem *cs, char *name,
+               unsigned int idx_vbn, unsigned int idx_off)
+{
+  if (cs->nbr == cs->max)
+    {
+      struct carsym *n;
+
+      cs->max = 2 * cs->max + 32;
+
+      if (!cs->realloced)
+        {
+          n = bfd_malloc2 (cs->max, sizeof (struct carsym));
+          if (n == NULL)
+            return FALSE;
+          memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym));
+          /* And unfortunately we can't free cs->idx.  */
+        }
+      else
+        {
+          n = bfd_realloc_or_free (cs->idx, cs->nbr * sizeof (struct carsym));
+          if (n == NULL)
+            return FALSE;
+        }
+      cs->idx = n;
+      cs->realloced = TRUE;
+    }
+  cs->idx[cs->nbr].file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
+  cs->idx[cs->nbr].name = name;
+  cs->nbr++;
+  return TRUE;
+}
+
+/* Follow all member of a lns list (pointed by RFA) and add indexes for
+   NAME.  Return FALSE in case of error.  */
+
+static bfd_boolean
+vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
+                           struct vms_rfa *rfa)
+{
+  struct vms_lns lns;
+  unsigned int vbn;
+  file_ptr off;
+
+  while (1)
+    {
+      vbn = bfd_getl32 (rfa->vbn);
+      if (vbn == 0)
+        return TRUE;
+
+      /* Read the LHS.  */
+      off = (vbn - 1) * VMS_BLOCK_SIZE + bfd_getl16 (rfa->offset);
+      if (bfd_seek (abfd, off, SEEK_SET) != 0
+          || bfd_bread (&lns, sizeof (lns), abfd) != sizeof (lns))
+        return FALSE;
+
+      if (!vms_add_index (cs, name,
+                          bfd_getl32 (lns.modrfa.vbn),
+                          bfd_getl16 (lns.modrfa.offset)))
+        return FALSE;
+
+      rfa = &lns.nxtrfa;
+    }
+}
+
 /* Read index block VBN and put the entry in **IDX (which is updated).
    If the entry is indirect, recurse.  */
 
 static bfd_boolean
-vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym **idx)
+vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs)
 {
   struct vms_indexdef indexdef;
-  unsigned int used;
   file_ptr off;
-  unsigned int i;
+  unsigned char *p;
+  unsigned char *endp;
 
   /* Read the index block.  */
   off = (vbn - 1) * VMS_BLOCK_SIZE;
@@ -112,44 +204,54 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym **idx)
     return FALSE;
 
   /* Traverse it.  */
-  used = bfd_getl16 (indexdef.used);
-  for (i = 0; i < used;)
+  p = &indexdef.keys[0];
+  endp = p + bfd_getl16 (indexdef.used);
+  while (p < endp)
     {
       unsigned int idx_vbn;
       unsigned int idx_off;
       unsigned int keylen;
       unsigned char *keyname;
-      unsigned char *ridx = (unsigned char *)&indexdef.keys[i];
-      unsigned int len;
-
-      idx_vbn = bfd_getl32 (ridx);
-      idx_off = bfd_getl16 (ridx + 4);
-
-      /* Illegal value.  */
-      if (idx_vbn == 0)
-        return FALSE;
+      unsigned int flags;
 
       /* Extract key length.  */
-      if (bfd_libdata (abfd)->ver == 3)
+      if (bfd_libdata (abfd)->ver == LBR_MAJORID)
         {
-          keylen = ridx[6];
-          len = 7;
+          struct vms_idx *ridx = (struct vms_idx *)p;
+
+          idx_vbn = bfd_getl32 (ridx->rfa.vbn);
+          idx_off = bfd_getl16 (ridx->rfa.offset);
+
+          keylen = ridx->keylen;
+          flags = 0;
+          keyname = ridx->keyname;
         }
-      else if (bfd_libdata (abfd)->ver == 4)
+      else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID)
         {
-          keylen = bfd_getl16 (ridx + 6);
-          len = 9;
+          struct vms_elfidx *ridx = (struct vms_elfidx *)p;
+
+          idx_vbn = bfd_getl32 (ridx->rfa.vbn);
+          idx_off = bfd_getl16 (ridx->rfa.offset);
+
+          keylen = bfd_getl16 (ridx->keylen);
+          flags = ridx->flags;
+          keyname = ridx->keyname;
         }
       else
         return FALSE;
 
-      keyname = ridx + len;
-      i += len + keylen;
+      /* Illegal value.  */
+      if (idx_vbn == 0)
+        return FALSE;
+
+      /* Long symbol names are not yet supported.  */
+      if (flags & ELFIDX__SYMESC)
+        return FALSE;
 
       if (idx_off == RFADEF__C_INDEX)
         {
           /* Indirect entry.  Recurse.  */
-          if (!vms_traverse_index (abfd, idx_vbn, idx))
+          if (!vms_traverse_index (abfd, idx_vbn, cs))
             return FALSE;
         }
       else
@@ -162,10 +264,36 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym **idx)
             return FALSE;
           memcpy (name, keyname, keylen);
           name[keylen] = 0;
-          (*idx)->file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
-          (*idx)->name = name;
-          (*idx)++;
+
+          if (flags & ELFIDX__LISTRFA)
+            {
+              struct vms_lhs lhs;
+
+              /* Read the LHS.  */
+              off = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
+              if (bfd_seek (abfd, off, SEEK_SET) != 0
+                  || bfd_bread (&lhs, sizeof (lhs), abfd) != sizeof (lhs))
+                return FALSE;
+
+              /* FIXME: this adds extra entries that were not accounted.  */
+              if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_g_rfa))
+                return FALSE;
+              if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_wk_rfa))
+                return FALSE;
+              if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_g_rfa))
+                return FALSE;
+              if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_wk_rfa))
+                return FALSE;
+            }
+          else
+            {
+              if (!vms_add_index (cs, name, idx_vbn, idx_off))
+                return FALSE;
+            }
         }
+
+      /* Point to the next index entry.  */
+      p = keyname + keylen;
     }
 
   return TRUE;
@@ -174,13 +302,13 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym **idx)
 /* Read index #IDX, which must have NBREL entries.  */
 
 static struct carsym *
-vms_lib_read_index (bfd *abfd, int idx, unsigned int nbrel)
+vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
 {
-  struct carsym *res;
-  struct carsym *el;
   struct vms_idd idd;
   unsigned int flags;
   unsigned int vbn;
+  struct carsym *csbuf;
+  struct carsym_mem csm;
 
   /* Read index desription.  */
   if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0
@@ -193,28 +321,40 @@ vms_lib_read_index (bfd *abfd, int idx, unsigned int nbrel)
       || !(flags & IDD__FLAGS_VARLENIDX))
     return NULL;
 
-  res = bfd_alloc (abfd, nbrel * sizeof (struct carsym));
-  if (res == NULL)
+  csbuf = bfd_alloc (abfd, *nbrel * sizeof (struct carsym));
+  if (csbuf == NULL)
     return NULL;
 
-  el = res;
+  csm.max = *nbrel;
+  csm.nbr = 0;
+  csm.realloced = FALSE;
+  csm.idx = csbuf;
 
   /* Note: if the index is empty, there is no block to traverse.  */
   vbn = bfd_getl32 (idd.vbn);
-  if (vbn != 0 && !vms_traverse_index (abfd, vbn, &el))
+  if (vbn != 0 && !vms_traverse_index (abfd, vbn, &csm))
     {
-      bfd_release (abfd, res);
+      if (csm.realloced && csm.idx != NULL)
+        free (csm.idx);
+
+      /* Note: in case of error, we can free what was allocated on the
+         BFD's objalloc.  */
+      bfd_release (abfd, csbuf);
       return NULL;
     }
 
-  if ((unsigned int)(el - res) != nbrel)
+  if (csm.realloced)
     {
-      /* Inconsistency between the number of modules declared and the number
-         of modules found in the index.  */
-      bfd_release (abfd, res);
-      return NULL;
+      /* There are more entries than the first estimate.  Allocate on
+         the BFD's objalloc.  */
+      csbuf = bfd_alloc (abfd, csm.nbr * sizeof (struct carsym));
+      if (csbuf == NULL)
+        return NULL;
+      memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym));
+      free (csm.idx);
+      *nbrel = csm.nbr;
     }
-  return res;
+  return csbuf;
 }
 
 /* Standard function.  */
@@ -227,6 +367,7 @@ _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
   struct lib_tdata *tdata_hold;
   struct lib_tdata *tdata;
   unsigned int dcxvbn;
+  unsigned int nbr_ent;
 
   /* Read header.  */
   if (bfd_bread (&lhd, sizeof (lhd), abfd) != sizeof (lhd))
@@ -239,7 +380,7 @@ _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
   /* Check sanity (= magic) number.  */
   sanity = bfd_getl32 (lhd.sanity);
   if (!(sanity == LHD_SANEID3
-        || sanity == LHD_SANEID4
+        || sanity == LHD_SANEID6
         || sanity == LHD_SANEID_DCX))
     {
       bfd_set_error (bfd_error_wrong_format);
@@ -258,6 +399,15 @@ _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
           return NULL;
         }
       break;
+    case vms_lib_ia64:
+      if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB)
+          || bfd_getl32 (lhd.majorid) != 6
+          || lhd.nindex != 2)
+        {
+          bfd_set_error (bfd_error_wrong_format);
+          return NULL;
+        }
+      break;
     case vms_lib_txt:
       if ((lhd.type != LBR__C_TYP_TXT
            && lhd.type != LBR__C_TYP_MLB
@@ -286,15 +436,23 @@ _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
 
   /* Read indexes.  */
   tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
-  tdata->nbr_syms = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules;
-  tdata->modules = vms_lib_read_index (abfd, 0, tdata->nbr_modules);
-  if (tdata->modules == NULL)
+  tdata->artdata.symdef_count = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules;
+  nbr_ent = tdata->nbr_modules;
+  tdata->modules = vms_lib_read_index (abfd, 0, &nbr_ent);
+  if (tdata->modules == NULL || nbr_ent != tdata->nbr_modules)
     goto err;
   if (lhd.nindex == 2)
     {
-      tdata->syms = vms_lib_read_index (abfd, 1, tdata->nbr_syms);
-      if (tdata->syms == NULL)
+      nbr_ent = tdata->artdata.symdef_count;
+      tdata->artdata.symdefs = vms_lib_read_index (abfd, 1, &nbr_ent);
+      if (tdata->artdata.symdefs == NULL)
+        goto err;
+      /* Only IA64 archives may have more entries in the index that what
+         was declared.  */
+      if (nbr_ent != tdata->artdata.symdef_count
+          && kind != vms_lib_ia64)
         goto err;
+      tdata->artdata.symdef_count = nbr_ent;
     }
   tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
   if (tdata->cache == NULL)
@@ -368,7 +526,7 @@ _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
 
   /* The map is always present.  Also mark shared image library.  */
   abfd->has_armap = TRUE;
-  if (tdata->type == LBR__C_TYP_ESHSTB)
+  if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB)
     abfd->is_thin_archive = TRUE;
 
   return abfd->xvec;
@@ -412,9 +570,9 @@ _bfd_vms_lib_mkarchive (bfd *abfd)
   tdata->type = LBR__C_TYP_EOBJ;
 
   tdata->nbr_modules = 0;
-  tdata->nbr_syms = 0;
+  tdata->artdata.symdef_count = 0;
   tdata->modules = NULL;
-  tdata->syms = NULL;
+  tdata->artdata.symdefs = NULL;
   tdata->cache = NULL;
 
   return TRUE;
@@ -426,28 +584,29 @@ symindex
 _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
 {
   struct lib_tdata *tdata = bfd_libdata (abfd);
+  carsym *syms = tdata->artdata.symdefs;
   int lo, hi;
 
   /* Open-coded binary search for speed.  */
   lo = 0;
-  hi = tdata->nbr_syms - 1;
+  hi = tdata->artdata.symdef_count - 1;
 
   while (lo <= hi)
     {
       int mid = lo + (hi - lo) / 2;
       int diff;
 
-      diff = (char)(name[0] - tdata->syms[mid].name[0]);
+      diff = (char)(name[0] - syms[mid].name[0]);
       if (diff == 0)
-        diff = strcmp (name, tdata->syms[mid].name);
+        diff = strcmp (name, syms[mid].name);
       if (diff == 0)
-        return tdata->syms[mid].file_offset;
+        return mid;
       else if (diff < 0)
         hi = mid - 1;
       else
         lo = mid + 1;
     }
-  return 0;
+  return BFD_NO_MORE_SYMBOLS;
 }
 
 /* IO vector for archive member.  Need that because members are not linearly
@@ -955,16 +1114,19 @@ vms_lib_bopen (bfd *el, file_ptr filepos)
   /* Read Record length + MHD + align byte.  */
   len = tdata->mhd_size;
   if (vms_lib_bread_raw (el, buf, 2) != 2)
-    return -1;
+    return FALSE;
   if (bfd_getl16 (buf) != len)
-    return -1;
+    return FALSE;
   len = (len + 1) & ~1;
   BFD_ASSERT (len <= sizeof (buf));
   if (vms_lib_bread_raw (el, buf, len) != len)
-    return -1;
+    return FALSE;
 
   /* Get info from mhd.  */
   mhd = (struct vms_mhd *)buf;
+  /* Check id.  */
+  if (mhd->id != MHD__C_MHDID)
+    return FALSE;
   if (len >= sizeof (struct vms_mhd))
     el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
   el->mtime = vms_rawtime_to_time_t (mhd->datim);
@@ -990,41 +1152,108 @@ vms_lib_bopen (bfd *el, file_ptr filepos)
   return TRUE;
 }
 
-/* Standard function: get member at IDX.  */
+/* Get member MODIDX.  Return NULL in case of error.  */
 
-bfd *
-_bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex idx)
+static bfd *
+_bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
 {
   struct lib_tdata *tdata = bfd_libdata (abfd);
   bfd *res;
-  unsigned int i;
+  file_ptr file_off;
 
-  /* Linear-scan.  */
-  for (i = 0; i < tdata->nbr_modules; i++)
-    {
-      if (tdata->modules[i].file_offset == (file_ptr)idx)
-        break;
-    }
-
-  /* Invalid index.  */
-  if (i >= tdata->nbr_modules)
+  /* Sanity check.  */
+  if (modidx >= tdata->nbr_modules)
     return NULL;
 
   /* Already loaded.  */
-  if (tdata->cache[i])
-    return tdata->cache[i];
+  if (tdata->cache[modidx])
+    return tdata->cache[modidx];
 
   /* Build it.  */
-  res = _bfd_create_empty_archive_element_shell (abfd);
-  if (!vms_lib_bopen (res, idx))
-    return NULL;
-  res->filename = tdata->modules[i].name;
+  file_off = tdata->modules[modidx].file_offset;
+  if (tdata->type != LBR__C_TYP_IOBJ)
+    {
+      res = _bfd_create_empty_archive_element_shell (abfd);
+      if (res == NULL)
+        return NULL;
+
+      /* Special reader to deal with data blocks.  */
+      if (!vms_lib_bopen (res, file_off))
+        return NULL;
+    }
+  else
+    {
+      char buf[256];
+      struct vms_mhd *mhd;
+      struct areltdata *arelt;
+
+      /* Sanity check.  The MHD must be big enough to contain module size.  */
+      if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4)
+        return NULL;
+
+      /* Read the MHD now.  */
+      if (bfd_seek (abfd, file_off, SEEK_SET) != 0)
+        return NULL;
+      if (bfd_bread (buf, tdata->mhd_size, abfd) != tdata->mhd_size)
+        return NULL;
+
+      res = _bfd_create_empty_archive_element_shell (abfd);
+      if (res == NULL)
+        return NULL;
+      arelt = bfd_zalloc (res, sizeof (*arelt));
+      if (arelt == NULL)
+        return NULL;
+      res->arelt_data = arelt;
+
+      /* Get info from mhd.  */
+      mhd = (struct vms_mhd *)buf;
+      if (mhd->id != MHD__C_MHDID)
+        return NULL;
+      if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1)
+        res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
+      res->mtime = vms_rawtime_to_time_t (mhd->datim);
+      res->mtime_set = TRUE;
+
+      arelt->parsed_size = bfd_getl32 (mhd->modsize);
+
+      /* No need for a special reader as members are stored linearly.
+         Just skip the MHD.  */
+      res->origin = file_off + tdata->mhd_size;
+    }
+
+  res->filename = tdata->modules[modidx].name;
 
-  tdata->cache[i] = res;
+  tdata->cache[modidx] = res;
 
   return res;
 }
 
+/* Standard function: get member at IDX.  */
+
+bfd *
+_bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
+{
+  struct lib_tdata *tdata = bfd_libdata (abfd);
+  file_ptr file_off;
+  unsigned int modidx;
+
+  /* Check symidx.  */
+  if (symidx > tdata->artdata.symdef_count)
+    return NULL;
+  file_off = tdata->artdata.symdefs[symidx].file_offset;
+
+  /* Linear-scan.  */
+  for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
+    {
+      if (tdata->modules[modidx].file_offset == file_off)
+        break;
+    }
+  if (modidx >= tdata->nbr_modules)
+    return NULL;
+
+  return _bfd_vms_lib_get_module (abfd, modidx);
+}
+
 /* Elements of an imagelib are stubs.  You can get the real image with this
    function.  */
 
@@ -1086,8 +1315,7 @@ _bfd_vms_lib_openr_next_archived_file (bfd *archive,
       return NULL;
     }
 
-  res = _bfd_vms_lib_get_elt_at_index
-    (archive, bfd_libdata (archive)->modules[idx].file_offset);
+  res = _bfd_vms_lib_get_module (archive, idx);
   if (res == NULL)
     return res;
   res->proxy_origin = idx;
@@ -1099,25 +1327,36 @@ _bfd_vms_lib_openr_next_archived_file (bfd *archive,
 int
 _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
 {
-  struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
+  struct lib_tdata *tdata;
 
+  /* Sanity check.  */
   if (abfd->my_archive == NULL)
     {
       bfd_set_error (bfd_error_invalid_operation);
       return -1;
     }
 
-  if (vec->file_len == (ufile_ptr)-1)
+  tdata = bfd_libdata (abfd->my_archive);
+  if (tdata->type != LBR__C_TYP_IOBJ)
     {
-      if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
-        return -1;
+      struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
 
-      /* Compute length.  */
-      while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
-        ;
+      if (vec->file_len == (ufile_ptr)-1)
+        {
+          if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
+            return -1;
+
+          /* Compute length.  */
+          while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
+            ;
+        }
+      st->st_size = vec->file_len;
+    }
+  else
+    {
+      st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
     }
 
-  st->st_size = vec->file_len;
   if (abfd->mtime_set)
     st->st_mtime = abfd->mtime;
   else
@@ -1213,7 +1452,7 @@ vms_write_index (bfd *abfd,
   for (i = 0; i < nbr; i++, idx++)
     {
       unsigned int idxlen = get_idxlen (idx);
-      struct vms_idxdef *en;
+      struct vms_idx *en;
       int flush = 0;
 
       /* Check if a block might overflow.  In this case we will flush this
@@ -1249,13 +1488,12 @@ vms_write_index (bfd *abfd,
               /* Update parent block: write the new entry.  */
               if (abfd != NULL)
                 {
-                  en = (struct vms_idxdef *)(rblk[j]->keys + blk[j].len);
+                  en = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
                   memcpy (rblk[j + 1]->keys + blk[j + 1].len, en,
                           blk[j].lastlen);
-                  en = (struct vms_idxdef *)
-                    (rblk[j + 1]->keys + blk[j + 1].len);
-                  bfd_putl32 (blk[j].vbn, en->vbn);
-                  bfd_putl16 (RFADEF__C_INDEX, en->offset);
+                  en = (struct vms_idx *)(rblk[j + 1]->keys + blk[j + 1].len);
+                  bfd_putl32 (blk[j].vbn, en->rfa.vbn);
+                  bfd_putl16 (RFADEF__C_INDEX, en->rfa.offset);
                 }
 
               if (j + 1 == flush)
@@ -1292,12 +1530,12 @@ vms_write_index (bfd *abfd,
 
               if (abfd != NULL)
                 {
-                  en = (struct vms_idxdef *)(rblk[j]->keys + blk[j].len);
+                  en = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
                   bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
-                              en->vbn);
+                              en->rfa.vbn);
                   bfd_putl16
                     ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE) + DATA__DATA,
-                     en->offset);
+                     en->rfa.offset);
                   en->keylen = idx->namlen;
                   memcpy (en->keyname, idx->name, idx->namlen);
                 }
@@ -1319,14 +1557,14 @@ vms_write_index (bfd *abfd,
       if (j > 0)
         {
           /* Update parent block: write the new entry.  */
-          struct vms_idxdef *en;
-          struct vms_idxdef *par;
+          struct vms_idx *en;
+          struct vms_idx *par;
 
-          en = (struct vms_idxdef *)(rblk[j - 1]->keys + blk[j - 1].len);
-          par = (struct vms_idxdef *)(rblk[j]->keys + blk[j].len);
+          en = (struct vms_idx *)(rblk[j - 1]->keys + blk[j - 1].len);
+          par = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
           memcpy (par, en, blk[j - 1].lastlen);
-          bfd_putl32 (blk[j - 1].vbn, par->vbn);
-          bfd_putl16 (RFADEF__C_INDEX, par->offset);
+          bfd_putl32 (blk[j - 1].vbn, par->rfa.vbn);
+          bfd_putl16 (RFADEF__C_INDEX, par->rfa.offset);
         }
 
       /* Write this block on the disk.  */
index e6945f3..b7114d3 100644 (file)
@@ -1,3 +1,20 @@
+2010-04-30  Tristan Gingold  <gingold@adacore.com>
+
+       * lbr.h (LBR__C_TYP_ISHSTB): Added.
+       (LHD_SANEID4): Renamed to ...
+       (LHD_SANEID6): ...  this.
+       (LBR_MAJORID, LBR_ELFMAJORID): New macros.
+       (struct vms_rfa): New structure.
+       (struct vms_idxdef): Renamed to ...
+       (struct vms_idx): ... this.
+       (struct vms_idxdef2): Renamed to ...
+       (struct vms_elfidx): ... this.
+       (ELFIDX__WEAK, ELFIDX__GROUP, ELFIDX__LISTRFA, ELFIDX__SYMESC): New
+       macros.
+       (struct vms_lhs, struct vms_lns): New structures.
+       (struct vms_mhd): Add missing fields.
+       (MHD__C_MHDLEN): New macro.
+
 2010-03-31  Tristan Gingold  <gingold@adacore.com>
 
        * dcx.h: New file.
index 768bc4c..7d6f597 100644 (file)
 
 /* Libray HeaDer.  */
 
+/* Magic numbers.  Should match the major version.  */
+
 #define LHD_SANEID_DCX 319232342
 #define LHD_SANEID3 233579905
-#define LHD_SANEID4 233579911
+#define LHD_SANEID6 233579911
 
 /* Library type.  */
 #define LBR__C_TYP_UNK    0    /* Unknown / unspecified.  */
@@ -40,6 +42,7 @@
 #define LBR__C_TYP_EOBJ   7    /* Alpha object.  */
 #define LBR__C_TYP_ESHSTB 8    /* Alpha shareable image.  */
 #define LBR__C_TYP_IOBJ   9    /* IA-64 object.  */
+#define LBR__C_TYP_ISHSTB 10   /* IA-64 shareable image.  */
 
 struct vms_lhd
 {
@@ -120,6 +123,10 @@ struct vms_lhd
   unsigned char fill_4[4 * 13];
 };
 
+/* Known major ids.  */
+#define LBR_MAJORID 3          /* Alpha libraries.  */
+#define LBR_ELFMAJORID 6       /* Elf libraries (new index, new data).  */
+
 /* Offset of the first IDD.  */
 #define LHD_IDXDESC 196
 
@@ -158,34 +165,80 @@ struct vms_indexdef
   unsigned char parent[4];
 
   unsigned char fill_1[6];
+
+  /* The key field contains vms_idxdef/vms_idxdef2 structures, which are
+     simply a key (= a string) and a rfa.  */
   unsigned char keys[INDEXDEF__BLKSIZ];
 };
 
-/* Index keys.  */
-struct vms_idxdef
+/* An offset in a file.  */
+
+struct vms_rfa
 {
+  /* Logical block number, 1 based.
+     0 means that the field is absent.  Block size is 512.  */
   unsigned char vbn[4];
+
+  /* Offset within the block.  */
   unsigned char offset[2];
+};
+
+/* Index keys.  For version 3.  */
+
+struct vms_idx
+{
+  /* Offset from the start of the vbn, so minimum should be
+     DATA__DATA (ie 6).  */
+  struct vms_rfa rfa;
 
   unsigned char keylen;
+  /* The length of this field is in fact keylen.  */
   unsigned char keyname[256];
 };
 
-struct vms_idxdef2
-{
-  unsigned char vbn[4];
+/* Index keys, for version 4 and later.  */
 
-  /* Offset from the start of the vbn, so minimum should be
-     DATA__DATA (ie 6).  */
-  unsigned char offset[2];
+struct vms_elfidx
+{
+  struct vms_rfa rfa;
 
   unsigned char keylen[2];
-  unsigned char fill_1;
+  unsigned char flags;
   unsigned char keyname[256];
 };
 
+/* Flags of elfidx.  */
+
+#define ELFIDX__WEAK 0x01      /* Weak symbol.  */
+#define ELFIDX__GROUP 0x02     /* Group symbol.  */
+#define ELFIDX__LISTRFA 0x04   /* RFA field points to an LHS.  */
+#define ELFIDX__SYMESC 0x08    /* Long symbol.  */
+
 #define RFADEF__C_INDEX 0xffff
 
+/* List head structure.  That's what is pointed by rfa when LISTRFA flag
+   is set in elfidx.  */
+
+struct vms_lhs
+{
+  struct vms_rfa ng_g_rfa;     /* Non-group global.  */
+  struct vms_rfa ng_wk_rfa;    /* Non-group weak.  */
+  struct vms_rfa g_g_rfa;      /* Group global.  */
+  struct vms_rfa g_wk_rfa;     /* Group weak.  */
+  unsigned char flags;
+};
+
+/* List node structure.  Fields of LHS point to this structure.  */
+
+struct vms_lns
+{
+  /* Next node in the list.  */
+  struct vms_rfa nxtrfa;
+
+  /* Module associated with the key.  */
+  struct vms_rfa modrfa;
+};
+
 struct vms_datadef
 {
   /* Number of records in this block.  */
@@ -216,9 +269,15 @@ struct vms_mhd
   /* Ident or GSMATCH.  */
   unsigned char objidlng;
   unsigned char objid[31];
+
+  unsigned char pad1[3];
+  unsigned char otherefcnt[4];
+  unsigned char modsize[4];
+  unsigned char pad2[4];
 };
 
 #define MHD__C_MHDID 0xad      /* Value for id.  */
+#define MHD__C_MHDLEN 16       /* Fixed part length.  */
 #define MHD__C_USRDAT 16
 #define MHD__M_SELSRC 0x1
 #define MHD__M_OBJTIR 0x2