This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[VMS/committed]: Preliminary work to support VMS/ia64 archives


Hi,

I am going to commit this patch to support VMS ia64 archives.  The format is slightly different from
VMS Alpha archives so it required a little bit of rework.

Also, this patch has slightly changed internal structures so now 'nm -s' works on VMS archives.

Tristan.

bfd/
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.

Index: bfd/vms-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-alpha.c,v
retrieving revision 1.3
diff -c -p -r1.3 vms-alpha.c
*** bfd/vms-alpha.c	16 Apr 2010 14:38:54 -0000	1.3
--- bfd/vms-alpha.c	30 Apr 2010 09:27:14 -0000
*************** alpha_vms_link_add_archive_symbols (bfd 
*** 8040,8046 ****
    for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef)
      {
        struct bfd_link_hash_entry *h;
!       file_ptr file_offset;
        bfd *element;
        bfd *orig_element;
  
--- 8040,8046 ----
    for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef)
      {
        struct bfd_link_hash_entry *h;
!       symindex symidx;
        bfd *element;
        bfd *orig_element;
  
*************** alpha_vms_link_add_archive_symbols (bfd 
*** 8066,8079 ****
  	}
  
        /* Look for this symbol in the archive hash table.  */
!       file_offset = _bfd_vms_lib_find_symbol (abfd, h->root.string);
!       if (file_offset == 0)
  	{
  	  /* Nothing in this slot.  */
  	  continue;
  	}
  
!       element = bfd_get_elt_at_index (abfd, file_offset);
        if (element == NULL)
  	return FALSE;
  
--- 8066,8079 ----
  	}
  
        /* Look for this symbol in the archive hash table.  */
!       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, symidx);
        if (element == NULL)
  	return FALSE;
  
Index: bfd/vms-lib.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-lib.c,v
retrieving revision 1.3
diff -c -p -r1.3 vms-lib.c
*** bfd/vms-lib.c	16 Apr 2010 14:23:41 -0000	1.3
--- bfd/vms-lib.c	30 Apr 2010 09:27:14 -0000
*************** enum vms_lib_kind
*** 62,67 ****
--- 62,70 ----
  
  struct lib_tdata
  {
+   /* Standard tdata for an archive.  But we don't use many fields.  */
+   struct artdata artdata;
+ 
    /* Major version.  */
    unsigned char ver;
  
*************** struct lib_tdata
*** 79,88 ****
    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;
--- 82,87 ----
*************** struct lib_tdata
*** 94,109 ****
  
  static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
  
  /* 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)
  {
    struct vms_indexdef indexdef;
-   unsigned int used;
    file_ptr off;
!   unsigned int i;
  
    /* Read the index block.  */
    off = (vbn - 1) * VMS_BLOCK_SIZE;
--- 93,201 ----
  
  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_mem *cs)
  {
    struct vms_indexdef indexdef;
    file_ptr off;
!   unsigned char *p;
!   unsigned char *endp;
  
    /* Read the index block.  */
    off = (vbn - 1) * VMS_BLOCK_SIZE;
*************** vms_traverse_index (bfd *abfd, unsigned 
*** 112,155 ****
      return FALSE;
  
    /* Traverse it.  */
!   used = bfd_getl16 (indexdef.used);
!   for (i = 0; i < used;)
      {
        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;
  
        /* Extract key length.  */
!       if (bfd_libdata (abfd)->ver == 3)
          {
!           keylen = ridx[6];
!           len = 7;
          }
!       else if (bfd_libdata (abfd)->ver == 4)
          {
!           keylen = bfd_getl16 (ridx + 6);
!           len = 9;
          }
        else
          return FALSE;
  
!       keyname = ridx + len;
!       i += len + keylen;
  
        if (idx_off == RFADEF__C_INDEX)
          {
            /* Indirect entry.  Recurse.  */
!           if (!vms_traverse_index (abfd, idx_vbn, idx))
              return FALSE;
          }
        else
--- 204,257 ----
      return FALSE;
  
    /* Traverse it.  */
!   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 int flags;
  
        /* Extract key length.  */
!       if (bfd_libdata (abfd)->ver == LBR_MAJORID)
          {
!           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 == LBR_ELFMAJORID)
          {
!           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;
  
!       /* 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, cs))
              return FALSE;
          }
        else
*************** vms_traverse_index (bfd *abfd, unsigned 
*** 162,171 ****
              return FALSE;
            memcpy (name, keyname, keylen);
            name[keylen] = 0;
!           (*idx)->file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
!           (*idx)->name = name;
!           (*idx)++;
          }
      }
  
    return TRUE;
--- 264,299 ----
              return FALSE;
            memcpy (name, keyname, keylen);
            name[keylen] = 0;
! 
!           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;
*************** vms_traverse_index (bfd *abfd, unsigned 
*** 174,186 ****
  /* Read index #IDX, which must have NBREL entries.  */
  
  static struct carsym *
! 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;
  
    /* Read index desription.  */
    if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0
--- 302,314 ----
  /* Read index #IDX, which must have NBREL entries.  */
  
  static struct carsym *
! vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
  {
    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
*************** vms_lib_read_index (bfd *abfd, int idx, 
*** 193,220 ****
        || !(flags & IDD__FLAGS_VARLENIDX))
      return NULL;
  
!   res = bfd_alloc (abfd, nbrel * sizeof (struct carsym));
!   if (res == NULL)
      return NULL;
  
!   el = res;
  
    /* 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))
      {
!       bfd_release (abfd, res);
        return NULL;
      }
  
!   if ((unsigned int)(el - res) != nbrel)
      {
!       /* Inconsistency between the number of modules declared and the number
!          of modules found in the index.  */
!       bfd_release (abfd, res);
!       return NULL;
      }
!   return res;
  }
  
  /* Standard function.  */
--- 321,360 ----
        || !(flags & IDD__FLAGS_VARLENIDX))
      return NULL;
  
!   csbuf = bfd_alloc (abfd, *nbrel * sizeof (struct carsym));
!   if (csbuf == NULL)
      return NULL;
  
!   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, &csm))
      {
!       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 (csm.realloced)
      {
!       /* 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 csbuf;
  }
  
  /* Standard function.  */
*************** _bfd_vms_lib_archive_p (bfd *abfd, enum 
*** 227,232 ****
--- 367,373 ----
    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))
*************** _bfd_vms_lib_archive_p (bfd *abfd, enum 
*** 239,245 ****
    /* Check sanity (= magic) number.  */
    sanity = bfd_getl32 (lhd.sanity);
    if (!(sanity == LHD_SANEID3
!         || sanity == LHD_SANEID4
          || sanity == LHD_SANEID_DCX))
      {
        bfd_set_error (bfd_error_wrong_format);
--- 380,386 ----
    /* Check sanity (= magic) number.  */
    sanity = bfd_getl32 (lhd.sanity);
    if (!(sanity == LHD_SANEID3
!         || sanity == LHD_SANEID6
          || sanity == LHD_SANEID_DCX))
      {
        bfd_set_error (bfd_error_wrong_format);
*************** _bfd_vms_lib_archive_p (bfd *abfd, enum 
*** 258,263 ****
--- 399,413 ----
            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
*************** _bfd_vms_lib_archive_p (bfd *abfd, enum 
*** 286,300 ****
  
    /* 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)
      goto err;
    if (lhd.nindex == 2)
      {
!       tdata->syms = vms_lib_read_index (abfd, 1, tdata->nbr_syms);
!       if (tdata->syms == NULL)
          goto err;
      }
    tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
    if (tdata->cache == NULL)
--- 436,458 ----
  
    /* Read indexes.  */
    tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
!   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)
      {
!       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)
*************** _bfd_vms_lib_archive_p (bfd *abfd, enum 
*** 368,374 ****
  
    /* The map is always present.  Also mark shared image library.  */
    abfd->has_armap = TRUE;
!   if (tdata->type == LBR__C_TYP_ESHSTB)
      abfd->is_thin_archive = TRUE;
  
    return abfd->xvec;
--- 526,532 ----
  
    /* The map is always present.  Also mark shared image library.  */
    abfd->has_armap = TRUE;
!   if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB)
      abfd->is_thin_archive = TRUE;
  
    return abfd->xvec;
*************** _bfd_vms_lib_mkarchive (bfd *abfd)
*** 412,420 ****
    tdata->type = LBR__C_TYP_EOBJ;
  
    tdata->nbr_modules = 0;
!   tdata->nbr_syms = 0;
    tdata->modules = NULL;
!   tdata->syms = NULL;
    tdata->cache = NULL;
  
    return TRUE;
--- 570,578 ----
    tdata->type = LBR__C_TYP_EOBJ;
  
    tdata->nbr_modules = 0;
!   tdata->artdata.symdef_count = 0;
    tdata->modules = NULL;
!   tdata->artdata.symdefs = NULL;
    tdata->cache = NULL;
  
    return TRUE;
*************** symindex
*** 426,453 ****
  _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
  {
    struct lib_tdata *tdata = bfd_libdata (abfd);
    int lo, hi;
  
    /* Open-coded binary search for speed.  */
    lo = 0;
!   hi = tdata->nbr_syms - 1;
  
    while (lo <= hi)
      {
        int mid = lo + (hi - lo) / 2;
        int diff;
  
!       diff = (char)(name[0] - tdata->syms[mid].name[0]);
        if (diff == 0)
!         diff = strcmp (name, tdata->syms[mid].name);
        if (diff == 0)
!         return tdata->syms[mid].file_offset;
        else if (diff < 0)
          hi = mid - 1;
        else
          lo = mid + 1;
      }
!   return 0;
  }
  
  /* IO vector for archive member.  Need that because members are not linearly
--- 584,612 ----
  _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->artdata.symdef_count - 1;
  
    while (lo <= hi)
      {
        int mid = lo + (hi - lo) / 2;
        int diff;
  
!       diff = (char)(name[0] - syms[mid].name[0]);
        if (diff == 0)
!         diff = strcmp (name, syms[mid].name);
        if (diff == 0)
!         return mid;
        else if (diff < 0)
          hi = mid - 1;
        else
          lo = mid + 1;
      }
!   return BFD_NO_MORE_SYMBOLS;
  }
  
  /* IO vector for archive member.  Need that because members are not linearly
*************** vms_lib_bopen (bfd *el, file_ptr filepos
*** 955,970 ****
    /* Read Record length + MHD + align byte.  */
    len = tdata->mhd_size;
    if (vms_lib_bread_raw (el, buf, 2) != 2)
!     return -1;
    if (bfd_getl16 (buf) != len)
!     return -1;
    len = (len + 1) & ~1;
    BFD_ASSERT (len <= sizeof (buf));
    if (vms_lib_bread_raw (el, buf, len) != len)
!     return -1;
  
    /* Get info from mhd.  */
    mhd = (struct vms_mhd *)buf;
    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);
--- 1114,1132 ----
    /* Read Record length + MHD + align byte.  */
    len = tdata->mhd_size;
    if (vms_lib_bread_raw (el, buf, 2) != 2)
!     return FALSE;
    if (bfd_getl16 (buf) != len)
!     return FALSE;
    len = (len + 1) & ~1;
    BFD_ASSERT (len <= sizeof (buf));
    if (vms_lib_bread_raw (el, buf, len) != len)
!     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);
*************** vms_lib_bopen (bfd *el, file_ptr filepos
*** 990,1030 ****
    return TRUE;
  }
  
! /* Standard function: get member at IDX.  */
  
! bfd *
! _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex idx)
  {
    struct lib_tdata *tdata = bfd_libdata (abfd);
    bfd *res;
!   unsigned int i;
! 
!   /* 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)
      return NULL;
  
    /* Already loaded.  */
!   if (tdata->cache[i])
!     return tdata->cache[i];
  
    /* Build it.  */
!   res = _bfd_create_empty_archive_element_shell (abfd);
!   if (!vms_lib_bopen (res, idx))
!     return NULL;
!   res->filename = tdata->modules[i].name;
  
!   tdata->cache[i] = res;
  
    return res;
  }
  
  /* Elements of an imagelib are stubs.  You can get the real image with this
     function.  */
  
--- 1152,1259 ----
    return TRUE;
  }
  
! /* Get member MODIDX.  Return NULL in case of error.  */
  
! static bfd *
! _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
  {
    struct lib_tdata *tdata = bfd_libdata (abfd);
    bfd *res;
!   file_ptr file_off;
  
!   /* Sanity check.  */
!   if (modidx >= tdata->nbr_modules)
      return NULL;
  
    /* Already loaded.  */
!   if (tdata->cache[modidx])
!     return tdata->cache[modidx];
  
    /* Build it.  */
!   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[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.  */
  
*************** _bfd_vms_lib_openr_next_archived_file (b
*** 1086,1093 ****
        return NULL;
      }
  
!   res = _bfd_vms_lib_get_elt_at_index
!     (archive, bfd_libdata (archive)->modules[idx].file_offset);
    if (res == NULL)
      return res;
    res->proxy_origin = idx;
--- 1315,1321 ----
        return NULL;
      }
  
!   res = _bfd_vms_lib_get_module (archive, idx);
    if (res == NULL)
      return res;
    res->proxy_origin = idx;
*************** _bfd_vms_lib_openr_next_archived_file (b
*** 1099,1123 ****
  int
  _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
  {
!   struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
  
    if (abfd->my_archive == NULL)
      {
        bfd_set_error (bfd_error_invalid_operation);
        return -1;
      }
  
!   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;
    if (abfd->mtime_set)
      st->st_mtime = abfd->mtime;
    else
--- 1327,1362 ----
  int
  _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
  {
!   struct lib_tdata *tdata;
  
+   /* Sanity check.  */
    if (abfd->my_archive == NULL)
      {
        bfd_set_error (bfd_error_invalid_operation);
        return -1;
      }
  
!   tdata = bfd_libdata (abfd->my_archive);
!   if (tdata->type != LBR__C_TYP_IOBJ)
      {
!       struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
  
!       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;
      }
  
    if (abfd->mtime_set)
      st->st_mtime = abfd->mtime;
    else
*************** vms_write_index (bfd *abfd,
*** 1213,1219 ****
    for (i = 0; i < nbr; i++, idx++)
      {
        unsigned int idxlen = get_idxlen (idx);
!       struct vms_idxdef *en;
        int flush = 0;
  
        /* Check if a block might overflow.  In this case we will flush this
--- 1452,1458 ----
    for (i = 0; i < nbr; i++, idx++)
      {
        unsigned int idxlen = get_idxlen (idx);
!       struct vms_idx *en;
        int flush = 0;
  
        /* Check if a block might overflow.  In this case we will flush this
*************** vms_write_index (bfd *abfd,
*** 1249,1261 ****
                /* Update parent block: write the new entry.  */
                if (abfd != NULL)
                  {
!                   en = (struct vms_idxdef *)(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);
                  }
  
                if (j + 1 == flush)
--- 1488,1499 ----
                /* Update parent block: write the new entry.  */
                if (abfd != NULL)
                  {
!                   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_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)
*************** vms_write_index (bfd *abfd,
*** 1292,1303 ****
  
                if (abfd != NULL)
                  {
!                   en = (struct vms_idxdef *)(rblk[j]->keys + blk[j].len);
                    bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
!                               en->vbn);
                    bfd_putl16
                      ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE) + DATA__DATA,
!                      en->offset);
                    en->keylen = idx->namlen;
                    memcpy (en->keyname, idx->name, idx->namlen);
                  }
--- 1530,1541 ----
  
                if (abfd != NULL)
                  {
!                   en = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
                    bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
!                               en->rfa.vbn);
                    bfd_putl16
                      ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE) + DATA__DATA,
!                      en->rfa.offset);
                    en->keylen = idx->namlen;
                    memcpy (en->keyname, idx->name, idx->namlen);
                  }
*************** vms_write_index (bfd *abfd,
*** 1319,1332 ****
        if (j > 0)
          {
            /* Update parent block: write the new entry.  */
!           struct vms_idxdef *en;
!           struct vms_idxdef *par;
  
!           en = (struct vms_idxdef *)(rblk[j - 1]->keys + blk[j - 1].len);
!           par = (struct vms_idxdef *)(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);
          }
  
        /* Write this block on the disk.  */
--- 1557,1570 ----
        if (j > 0)
          {
            /* Update parent block: write the new entry.  */
!           struct vms_idx *en;
!           struct vms_idx *par;
  
!           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->rfa.vbn);
!           bfd_putl16 (RFADEF__C_INDEX, par->rfa.offset);
          }
  
        /* Write this block on the disk.  */
Index: include/vms/lbr.h
===================================================================
RCS file: /cvs/src/src/include/vms/lbr.h,v
retrieving revision 1.1
diff -c -p -r1.1 lbr.h
*** include/vms/lbr.h	31 Mar 2010 07:35:54 -0000	1.1
--- include/vms/lbr.h	30 Apr 2010 09:27:17 -0000
***************
*** 25,33 ****
  
  /* Libray HeaDer.  */
  
  #define LHD_SANEID_DCX 319232342
  #define LHD_SANEID3 233579905
! #define LHD_SANEID4 233579911
  
  /* Library type.  */
  #define LBR__C_TYP_UNK    0	/* Unknown / unspecified.  */
--- 25,35 ----
  
  /* Libray HeaDer.  */
  
+ /* Magic numbers.  Should match the major version.  */
+ 
  #define LHD_SANEID_DCX 319232342
  #define LHD_SANEID3 233579905
! #define LHD_SANEID6 233579911
  
  /* Library type.  */
  #define LBR__C_TYP_UNK    0	/* Unknown / unspecified.  */
***************
*** 40,45 ****
--- 42,48 ----
  #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
  {
*************** struct vms_lhd
*** 120,125 ****
--- 123,132 ----
    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
  
*************** struct vms_indexdef
*** 158,191 ****
    unsigned char parent[4];
  
    unsigned char fill_1[6];
    unsigned char keys[INDEXDEF__BLKSIZ];
  };
  
! /* Index keys.  */
! struct vms_idxdef
  {
    unsigned char vbn[4];
    unsigned char offset[2];
  
    unsigned char keylen;
    unsigned char keyname[256];
  };
  
! struct vms_idxdef2
! {
!   unsigned char vbn[4];
  
!   /* Offset from the start of the vbn, so minimum should be
!      DATA__DATA (ie 6).  */
!   unsigned char offset[2];
  
    unsigned char keylen[2];
!   unsigned char fill_1;
    unsigned char keyname[256];
  };
  
  #define RFADEF__C_INDEX 0xffff
  
  struct vms_datadef
  {
    /* Number of records in this block.  */
--- 165,244 ----
    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];
  };
  
! /* 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];
  };
  
! /* Index keys, for version 4 and later.  */
  
! struct vms_elfidx
! {
!   struct vms_rfa rfa;
  
    unsigned char keylen[2];
!   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.  */
*************** struct vms_mhd
*** 216,224 ****
--- 269,283 ----
    /* 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]