[vms/committed]: Preliminary work to write vms/ia64 libraries

Tristan Gingold gingold@adacore.com
Mon May 31 15:03:00 GMT 2010


Hi,

on ia64, vms libraries format has slightly changed compared to alpha.  In particular, it is able to
handle longer symbol names.
This patch add support to vms-lib.c for ia64 libraries, without yet enabling it (will be for a following
patch).  However, it doesn't yet add support for multiple definition of symbols nor for weak and group
symbols.

This patch also renames a function from vms-lib.c declared in libbfd-in.h.  I commit this part as it is
obvious.

Tristan.

bfd/
2010-05-31  Tristan Gingold  <gingold@adacore.com>

	* vms-lib.c (credat_lo, credat_hi): New fields.
	(vms_read_block): Adjust comments.
	(vms_write_block): New function.
	(_bfd_vms_lib_archive_p): Decode majorid once.  Replace some
	hard-coded values with constants.  Set credat_lo and credat_hi.
	(_bfd_vms_lib_mkarchive): Add argument kind.
	Set ver, mhd_size and type according to kind.
	(_bfd_vms_lib_alpha_mkarchive): New function.
	(struct lib_index): Renamed from struct vms_index
	(lib_index_cmp): Renamed from vms_index_cmp.  Adjusted.
	(get_idxlen): Type of idx argument adjusted.  Add is_elfidx
	argument and handle it.
	(vms_write_index): Adjust argument idx.  Handle elf indexes.
	(_bfd_vms_lib_build_map): Adjust type of arguments modules and res.
	(_bfd_vms_lib_write_archive_contents): Add is_elfidx variable and
	use it.  Handle elf indexes.  Set credat.
	* libbfd-in.h (_bfd_vms_lib_mkarchive): Renamed to ...
	(_bfd_vms_lib_alpha_mkarchive): ... this.
	* libbfd.h: Regenerated.
	* vms-alpha.c (vms_alpha_vec): Adjust after previous renaming.

  
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.81
diff -c -r1.81 libbfd-in.h
*** bfd/libbfd-in.h	14 May 2010 07:18:39 -0000	1.81
--- bfd/libbfd-in.h	31 May 2010 15:01:12 -0000
***************
*** 376,382 ****
  extern bfd *_bfd_vms_lib_get_imagelib_file (bfd *);
  extern const bfd_target *_bfd_vms_lib_alpha_archive_p (bfd *abfd);
  extern const bfd_target *_bfd_vms_lib_ia64_archive_p (bfd *abfd);
! extern bfd_boolean _bfd_vms_lib_mkarchive (bfd *abfd);
  
  /* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol
     support.  Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols).  */
--- 376,382 ----
  extern bfd *_bfd_vms_lib_get_imagelib_file (bfd *);
  extern const bfd_target *_bfd_vms_lib_alpha_archive_p (bfd *abfd);
  extern const bfd_target *_bfd_vms_lib_ia64_archive_p (bfd *abfd);
! extern bfd_boolean _bfd_vms_lib_alpha_mkarchive (bfd *abfd);
  
  /* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol
     support.  Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols).  */

Index: bfd/vms-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-alpha.c,v
retrieving revision 1.18
diff -c -r1.18 vms-alpha.c
*** bfd/vms-alpha.c	26 May 2010 08:55:22 -0000	1.18
--- bfd/vms-alpha.c	31 May 2010 15:01:13 -0000
***************
*** 9231,9237 ****
    {_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_false, alpha_vms_write_object_contents,	/* bfd_write_contents.  */
     _bfd_vms_lib_write_archive_contents, bfd_false},
  
--- 9231,9237 ----
    {_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_alpha_mkarchive, bfd_false},
    {bfd_false, alpha_vms_write_object_contents,	/* bfd_write_contents.  */
     _bfd_vms_lib_write_archive_contents, bfd_false},
  
Index: bfd/vms-lib.c
===================================================================
RCS file: /cvs/src/src/bfd/vms-lib.c,v
retrieving revision 1.8
diff -c -r1.8 vms-lib.c
*** bfd/vms-lib.c	14 May 2010 07:18:39 -0000	1.8
--- bfd/vms-lib.c	31 May 2010 15:01:13 -0000
***************
*** 77,82 ****
--- 77,86 ----
    /* Total size of the mhd (element header).  */
    unsigned int mhd_size;
  
+   /* Creation date.  */
+   unsigned int credat_lo;
+   unsigned int credat_hi;
+ 
    /* Vector of modules (archive elements), already sorted.  */
    unsigned int nbr_modules;
    struct carsym *modules;
***************
*** 186,199 ****
      }
  }
  
! /* Read block VBN from ABFD and store it into BLK.  */
  
  static bfd_boolean
  vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
  {
    file_ptr off;
  
-   /* Read the index block.  */
    off = (vbn - 1) * VMS_BLOCK_SIZE;
    if (bfd_seek (abfd, off, SEEK_SET) != 0
        || bfd_bread (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE)
--- 190,202 ----
      }
  }
  
! /* Read block VBN from ABFD and store it into BLK.  Return FALSE in case of error.  */
  
  static bfd_boolean
  vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
  {
    file_ptr off;
  
    off = (vbn - 1) * VMS_BLOCK_SIZE;
    if (bfd_seek (abfd, off, SEEK_SET) != 0
        || bfd_bread (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE)
***************
*** 202,207 ****
--- 205,225 ----
    return TRUE;
  }
  
+ /* Write the content of BLK to block VBN of ABFD.  Return FALSE in case of error.  */
+ 
+ static bfd_boolean
+ vms_write_block (bfd *abfd, unsigned int vbn, void *blk)
+ {
+   file_ptr off;
+ 
+   off = (vbn - 1) * VMS_BLOCK_SIZE;
+   if (bfd_seek (abfd, off, SEEK_SET) != 0
+       || bfd_bwrite (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE)
+     return FALSE;
+ 
+   return TRUE;
+ }
+ 
  /* Read index block VBN and put the entry in **IDX (which is updated).
     If the entry is indirect, recurse.  */
  
***************
*** 423,428 ****
--- 441,447 ----
  {
    struct vms_lhd lhd;
    unsigned int sanity;
+   unsigned int majorid;
    struct lib_tdata *tdata_hold;
    struct lib_tdata *tdata;
    unsigned int dcxvbn;
***************
*** 445,457 ****
        bfd_set_error (bfd_error_wrong_format);
        return NULL;
      }
  
    /* Check archive kind.  */
    switch (kind)
      {
      case vms_lib_alpha:
        if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB)
!           || bfd_getl32 (lhd.majorid) != 3
            || lhd.nindex != 2)
          {
            bfd_set_error (bfd_error_wrong_format);
--- 464,477 ----
        bfd_set_error (bfd_error_wrong_format);
        return NULL;
      }
+   majorid = bfd_getl32 (lhd.majorid);
  
    /* Check archive kind.  */
    switch (kind)
      {
      case vms_lib_alpha:
        if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB)
!           || majorid != LBR_MAJORID
            || lhd.nindex != 2)
          {
            bfd_set_error (bfd_error_wrong_format);
***************
*** 460,466 ****
        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);
--- 480,486 ----
        break;
      case vms_lib_ia64:
        if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB)
!           || majorid != LBR_ELFMAJORID
            || lhd.nindex != 2)
          {
            bfd_set_error (bfd_error_wrong_format);
***************
*** 471,477 ****
        if ((lhd.type != LBR__C_TYP_TXT
             && lhd.type != LBR__C_TYP_MLB
             && lhd.type != LBR__C_TYP_HLP)
!           || bfd_getl32 (lhd.majorid) != 3
            || lhd.nindex != 1)
          {
            bfd_set_error (bfd_error_wrong_format);
--- 491,497 ----
        if ((lhd.type != LBR__C_TYP_TXT
             && lhd.type != LBR__C_TYP_MLB
             && lhd.type != LBR__C_TYP_HLP)
!           || majorid != LBR_MAJORID
            || lhd.nindex != 1)
          {
            bfd_set_error (bfd_error_wrong_format);
***************
*** 488,497 ****
    if (tdata == NULL)
      return NULL;
    abfd->tdata.any = (void *)tdata;
!   tdata->ver = bfd_getl32 (lhd.majorid);
    tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz;
    tdata->type = lhd.type;
    tdata->kind = kind;
  
    /* Read indexes.  */
    tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
--- 508,519 ----
    if (tdata == NULL)
      return NULL;
    abfd->tdata.any = (void *)tdata;
!   tdata->ver = majorid;
    tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz;
    tdata->type = lhd.type;
    tdata->kind = kind;
+   tdata->credat_lo = bfd_getl32 (lhd.credat + 0);
+   tdata->credat_hi = bfd_getl32 (lhd.credat + 4);
  
    /* Read indexes.  */
    tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
***************
*** 637,644 ****
  
  /* Standard bfd function.  */
  
! bfd_boolean
! _bfd_vms_lib_mkarchive (bfd *abfd)
  {
    struct lib_tdata *tdata;
  
--- 659,666 ----
  
  /* Standard bfd function.  */
  
! static bfd_boolean
! _bfd_vms_lib_mkarchive (bfd *abfd, enum vms_lib_kind kind)
  {
    struct lib_tdata *tdata;
  
***************
*** 647,655 ****
      return FALSE;
  
    abfd->tdata.any = (void *)tdata;
!   tdata->ver = 3;
!   tdata->mhd_size = sizeof (struct vms_mhd);
!   tdata->type = LBR__C_TYP_EOBJ;
  
    tdata->nbr_modules = 0;
    tdata->artdata.symdef_count = 0;
--- 669,692 ----
      return FALSE;
  
    abfd->tdata.any = (void *)tdata;
!   vms_get_time (&tdata->credat_hi, &tdata->credat_lo);
! 
!   tdata->kind = kind;
!   switch (kind)
!     {
!     case vms_lib_alpha:
!       tdata->ver = LBR_MAJORID;
!       tdata->mhd_size = offsetof (struct vms_mhd, pad1);
!       tdata->type = LBR__C_TYP_EOBJ;
!       break;
!     case vms_lib_ia64:
!       tdata->ver = LBR_ELFMAJORID;
!       tdata->mhd_size = sizeof (struct vms_mhd);
!       tdata->type = LBR__C_TYP_IOBJ;
!       break;
!     default:
!       abort ();
!     }
  
    tdata->nbr_modules = 0;
    tdata->artdata.symdef_count = 0;
***************
*** 660,665 ****
--- 697,708 ----
    return TRUE;
  }
  
+ bfd_boolean
+ _bfd_vms_lib_alpha_mkarchive (bfd *abfd)
+ {
+   return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha);
+ }
+ 
  /* Find NAME in the symbol index.  Return the index.  */
  
  symindex
***************
*** 1453,1459 ****
  
  /* Internal representation of an index entry.  */
  
! struct vms_index
  {
    /* Corresponding archive member.  */
    bfd *abfd;
--- 1496,1502 ----
  
  /* Internal representation of an index entry.  */
  
! struct lib_index
  {
    /* Corresponding archive member.  */
    bfd *abfd;
***************
*** 1471,1480 ****
  /* Used to sort index entries.  */
  
  static int
! vms_index_cmp (const void *lv, const void *rv)
  {
!   const struct vms_index *l = lv;
!   const struct vms_index *r = rv;
  
    return strcmp (l->name, r->name);
  }
--- 1514,1523 ----
  /* Used to sort index entries.  */
  
  static int
! lib_index_cmp (const void *lv, const void *rv)
  {
!   const struct lib_index *l = lv;
!   const struct lib_index *r = rv;
  
    return strcmp (l->name, r->name);
  }
***************
*** 1486,1494 ****
  /* Get the size of an index entry.  */
  
  static unsigned int
! get_idxlen (struct vms_index *idx)
  {
!   return 7 + idx->namlen;
  }
  
  /* Write the index.  VBN is the first vbn to be used, and will contain
--- 1529,1545 ----
  /* Get the size of an index entry.  */
  
  static unsigned int
! get_idxlen (struct lib_index *idx, bfd_boolean is_elfidx)
  {
!   if (is_elfidx)
!     {
!       if (idx->namlen > MAX_KEYLEN)
!         return 9 + sizeof (struct vms_rfa);
!       else
!         return 9 + idx->namlen;
!     }
!   else
!     return 7 + idx->namlen;
  }
  
  /* Write the index.  VBN is the first vbn to be used, and will contain
***************
*** 1497,1504 ****
  
  static bfd_boolean
  vms_write_index (bfd *abfd,
!                  struct vms_index *idx, unsigned int nbr, unsigned int *vbn,
!                  unsigned int *topvbn)
  {
    unsigned int i;
    int j;
--- 1548,1555 ----
  
  static bfd_boolean
  vms_write_index (bfd *abfd,
!                  struct lib_index *idx, unsigned int nbr, unsigned int *vbn,
!                  unsigned int *topvbn, bfd_boolean is_elfidx)
  {
    unsigned int i;
    int j;
***************
*** 1511,1518 ****
--- 1562,1575 ----
      unsigned short lastlen;
    } blk[MAX_LEVEL];
  
+   /* The kbn blocks are used to store long symbol names.  */
+   unsigned int kbn_sz = 0;	 /* Number of bytes availble in the kbn block.  */
+   unsigned int kbn_vbn = 0;	 /* VBN of the kbn block.  */
+   unsigned char *kbn_blk = NULL; /* Contents of the kbn block.  */
+ 
    if (nbr == 0)
      {
+       /* No entries.  Very easy to handle.  */
        if (topvbn != NULL)
          *topvbn = 0;
        return TRUE;
***************
*** 1521,1527 ****
    if (abfd == NULL)
      {
        /* Sort the index the first time this function is called.  */
!       qsort (idx, nbr, sizeof (struct vms_index), vms_index_cmp);
      }
  
    /* Allocate first index block.  */
--- 1578,1584 ----
    if (abfd == NULL)
      {
        /* Sort the index the first time this function is called.  */
!       qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp);
      }
  
    /* Allocate first index block.  */
***************
*** 1534,1542 ****
  
    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
           block and all the blocks below it.  */
--- 1591,1675 ----
  
    for (i = 0; i < nbr; i++, idx++)
      {
!       unsigned int idxlen;
        int flush = 0;
+       unsigned int key_vbn = 0;
+       unsigned int key_off = 0;
+ 
+       idxlen = get_idxlen (idx, is_elfidx);
+ 
+       if (is_elfidx && idx->namlen >= MAX_KEYLEN)
+         {
+           /* If the name is too long, write it in the kbn block.  */
+           unsigned int kl = idx->namlen;
+           unsigned int kl_chunk;
+           const char *key = idx->name;
+ 
+           /* Write the name in the kbn, chunk after chunk.  */
+           do
+             {
+               if (kbn_sz < sizeof (struct vms_kbn))
+                 {
+                   /* Not enough room in the kbn block.  */
+                   if (abfd != NULL)
+                     {
+                       /* Write it to the disk (if there is one).  */
+                       if (kbn_vbn != 0)
+                         {
+                           if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE)
+                             return FALSE;
+                         }
+                       else
+                         {
+                           kbn_blk = bfd_malloc (VMS_BLOCK_SIZE);
+                           if (kbn_blk == NULL)
+                             return FALSE;
+                         }
+                       *(unsigned short *)kbn_blk = 0;
+                     }
+                   kbn_vbn = (*vbn)++;
+                   kbn_sz = VMS_BLOCK_SIZE - 2;
+                 }
+               if (kl + sizeof (struct vms_kbn) > kbn_sz)
+                 kl_chunk = kbn_sz - sizeof (struct vms_kbn);
+               else
+                 kl_chunk = kl;
+ 
+               if (kbn_blk != NULL)
+                 {
+                   struct vms_kbn *kbn;
+ 
+                   kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz);
+ 
+                   if (key_vbn == 0)
+                     {
+                       /* Save the rfa of the first chunk.  */
+                       key_vbn = kbn_vbn;
+                       key_off = VMS_BLOCK_SIZE - kbn_sz;
+                     }
+ 
+                   bfd_putl16 (kl_chunk, kbn->keylen);
+                   if (kl_chunk == kl)
+                     {
+                       /* No next chunk.  */
+                       bfd_putl32 (0, kbn->rfa.vbn);
+                       bfd_putl16 (0, kbn->rfa.offset);
+                     }
+                   else
+                     {
+                       /* Next chunk will be at the start of the next block.  */
+                       bfd_putl32 (*vbn, kbn->rfa.vbn);
+                       bfd_putl16 (2, kbn->rfa.offset);
+                     }
+                   memcpy ((char *)(kbn + 1), key, kl_chunk);
+                   key += kl_chunk;
+                 }
+               kl -= kl_chunk;
+               kl_chunk = (kl_chunk + 1) & ~1;	  /* Always align.  */
+               kbn_sz -= kl_chunk + sizeof (struct vms_kbn);
+             }
+           while (kl > 0);
+         }
  
        /* Check if a block might overflow.  In this case we will flush this
           block and all the blocks below it.  */
***************
*** 1571,1582 ****
                /* 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)
--- 1704,1719 ----
                /* Update parent block: write the new entry.  */
                if (abfd != NULL)
                  {
!                   struct vms_rfa *rfa;
! 
!                   /* Copy the whole entry.  */
!                   memcpy (rblk[j + 1]->keys + blk[j + 1].len,
!                           rblk[j]->keys + blk[j].len,
                            blk[j].lastlen);
!                   /* Fix the entry (which in always the first field of an entry.  */
!                   rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len);
!                   bfd_putl32 (blk[j].vbn, rfa->vbn);
!                   bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
                  }
  
                if (j + 1 == flush)
***************
*** 1592,1602 ****
                if (abfd != NULL)
                  {
                    bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
!                   if (bfd_seek (abfd, (blk[j].vbn - 1) * VMS_BLOCK_SIZE,
!                                 SEEK_SET) != 0)
!                     return FALSE;
!                   if (bfd_bwrite (rblk[j], sizeof (struct vms_indexdef), abfd)
!                       != sizeof (struct vms_indexdef))
                      return FALSE;
                  }
  
--- 1729,1735 ----
                if (abfd != NULL)
                  {
                    bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
!                   if (vms_write_block (abfd, blk[j].vbn, rblk[j]) != TRUE)
                      return FALSE;
                  }
  
***************
*** 1613,1626 ****
  
                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);
                  }
              }
  
--- 1746,1790 ----
  
                if (abfd != NULL)
                  {
!                   struct vms_rfa *rfa;
! 
!                   rfa = (struct vms_rfa *)(rblk[j]->keys + blk[j].len);
                    bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
!                               rfa->vbn);
                    bfd_putl16
!                     ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE)
!                      + (is_elfidx ? 0 : DATA__DATA),
!                      rfa->offset);
! 
!                   if (is_elfidx)
!                     {
!                       /* Use elfidx format.  */
!                       struct vms_elfidx *en = (struct vms_elfidx *)rfa;
! 
!                       en->flags = 0;
!                       if (key_vbn != 0)
!                         {
!                           /* Long symbol name.  */
!                           struct vms_kbn *k = (struct vms_kbn *)(en->keyname);
!                           bfd_putl16 (sizeof (struct vms_kbn), en->keylen);
!                           bfd_putl16 (idx->namlen, k->keylen);
!                           bfd_putl32 (key_vbn, k->rfa.vbn);
!                           bfd_putl16 (key_off, k->rfa.offset);
!                           en->flags |= ELFIDX__SYMESC;
!                         }
!                       else
!                         {
!                           bfd_putl16 (idx->namlen, en->keylen);
!                           memcpy (en->keyname, idx->name, idx->namlen);
!                         }
!                     }
!                   else
!                     {
!                       /* Use idx format.  */
!                       struct vms_idx *en = (struct vms_idx *)rfa;
!                       en->keylen = idx->namlen;
!                       memcpy (en->keyname, idx->name, idx->namlen);
!                     }
                  }
              }
  
***************
*** 1640,1667 ****
        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.  */
        bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
!       if (bfd_seek (abfd, (blk[j].vbn - 1) * VMS_BLOCK_SIZE,
!                     SEEK_SET) != 0)
!         return FALSE;
!       if (bfd_bwrite (rblk[j], sizeof (struct vms_indexdef), abfd)
!           != sizeof (struct vms_indexdef))
          return FALSE;
  
        free (rblk[j]);
      }
  
    return TRUE;
  }
  
--- 1804,1835 ----
        if (j > 0)
          {
            /* Update parent block: write the new entry.  */
!           unsigned char *en;
!           unsigned char *par;
!           struct vms_rfa *rfa;
  
!           en = rblk[j - 1]->keys + blk[j - 1].len;
!           par = rblk[j]->keys + blk[j].len;
            memcpy (par, en, blk[j - 1].lastlen);
!           rfa = (struct vms_rfa *)par;
!           bfd_putl32 (blk[j - 1].vbn, rfa->vbn);
!           bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
          }
  
        /* Write this block on the disk.  */
        bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
!       if (vms_write_block (abfd, blk[j].vbn, rblk[j]) != TRUE)
          return FALSE;
  
        free (rblk[j]);
      }
  
+   if (kbn_vbn != 0)
+     {
+       if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE)
+         return FALSE;
+     }
+ 
    return TRUE;
  }
  
***************
*** 1706,1723 ****
  
  static bfd_boolean
  _bfd_vms_lib_build_map (unsigned int nbr_modules,
!                         struct vms_index *modules,
                          unsigned int *res_cnt,
!                         struct vms_index **res)
  {
    unsigned int i;
    asymbol **syms = NULL;
    long syms_max = 0;
!   struct vms_index *map = NULL;
    unsigned int map_max = 1024;		/* Fine initial default.  */
    unsigned int map_count = 0;
  
!   map = (struct vms_index *) bfd_malloc (map_max * sizeof (struct vms_index));
    if (map == NULL)
      goto error_return;
  
--- 1874,1891 ----
  
  static bfd_boolean
  _bfd_vms_lib_build_map (unsigned int nbr_modules,
!                         struct lib_index *modules,
                          unsigned int *res_cnt,
!                         struct lib_index **res)
  {
    unsigned int i;
    asymbol **syms = NULL;
    long syms_max = 0;
!   struct lib_index *map = NULL;
    unsigned int map_max = 1024;		/* Fine initial default.  */
    unsigned int map_count = 0;
  
!   map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index));
    if (map == NULL)
      goto error_return;
  
***************
*** 1764,1784 ****
                     || bfd_is_com_section (sec))
                    && ! bfd_is_und_section (sec))
                  {
!                   struct vms_index *new_map;
  
                    /* This symbol will go into the archive header.  */
                    if (map_count == map_max)
                      {
                        map_max *= 2;
!                       new_map = (struct vms_index *)
!                         bfd_realloc (map, map_max * sizeof (struct vms_index));
                        if (new_map == NULL)
                          goto error_return;
                        map = new_map;
                      }
  
                    map[map_count].abfd = current;
-                   /* FIXME: check length.  */
                    map[map_count].namlen = strlen (syms[src_count]->name);
                    map[map_count].name = syms[src_count]->name;
                    map_count++;
--- 1932,1951 ----
                     || bfd_is_com_section (sec))
                    && ! bfd_is_und_section (sec))
                  {
!                   struct lib_index *new_map;
  
                    /* This symbol will go into the archive header.  */
                    if (map_count == map_max)
                      {
                        map_max *= 2;
!                       new_map = (struct lib_index *)
!                         bfd_realloc (map, map_max * sizeof (struct lib_index));
                        if (new_map == NULL)
                          goto error_return;
                        map = new_map;
                      }
  
                    map[map_count].abfd = current;
                    map[map_count].namlen = strlen (syms[src_count]->name);
                    map[map_count].name = syms[src_count]->name;
                    map_count++;
***************
*** 1807,1815 ****
  {
    bfd *current;
    unsigned int nbr_modules;
!   struct vms_index *modules;
    unsigned int nbr_symbols;
!   struct vms_index *symbols;
    struct lib_tdata *tdata = bfd_libdata (arch);
    unsigned int i;
    file_ptr off;
--- 1974,1982 ----
  {
    bfd *current;
    unsigned int nbr_modules;
!   struct lib_index *modules;
    unsigned int nbr_symbols;
!   struct lib_index *symbols;
    struct lib_tdata *tdata = bfd_libdata (arch);
    unsigned int i;
    file_ptr off;
***************
*** 1818,1823 ****
--- 1985,1991 ----
    unsigned int vbn;
    unsigned int mod_idx_vbn;
    unsigned int sym_idx_vbn;
+   bfd_boolean is_elfidx = tdata->kind == vms_lib_ia64;
  
    /* Count the number of modules (and do a first sanity check).  */
    nbr_modules = 0;
***************
*** 1841,1847 ****
  
    /* Build the modules list.  */
    BFD_ASSERT (tdata->modules == NULL);
!   modules = bfd_alloc (arch, nbr_modules * sizeof (struct vms_index));
    if (modules == NULL)
      return FALSE;
  
--- 2009,2015 ----
  
    /* Build the modules list.  */
    BFD_ASSERT (tdata->modules == NULL);
!   modules = bfd_alloc (arch, nbr_modules * sizeof (struct lib_index));
    if (modules == NULL)
      return FALSE;
  
***************
*** 1862,1868 ****
  
    /* Create the module index.  */
    vbn = 0;
!   if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL))
      return FALSE;
    nbr_mod_iblk = vbn;
  
--- 2030,2036 ----
  
    /* Create the module index.  */
    vbn = 0;
!   if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL, is_elfidx))
      return FALSE;
    nbr_mod_iblk = vbn;
  
***************
*** 1871,1877 ****
      return FALSE;
  
    vbn = 0;
!   if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL))
      return FALSE;
    nbr_sym_iblk = vbn;
  
--- 2039,2045 ----
      return FALSE;
  
    vbn = 0;
!   if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx))
      return FALSE;
    nbr_sym_iblk = vbn;
  
***************
*** 1891,1898 ****
        current = modules[i].abfd;
        current->proxy_origin = off;
  
!       bfd_putl16 (sizeof (struct vms_mhd), blk);
!       mhd = (struct vms_mhd *)(blk + 2);
        memset (mhd, 0, sizeof (struct vms_mhd));
        mhd->lbrflag = 0;
        mhd->id = MHD__C_MHDID;
--- 2059,2073 ----
        current = modules[i].abfd;
        current->proxy_origin = off;
  
!       if (is_elfidx)
!         sz = 0;
!       else
!         {
!           /* Write the MHD as a record (ie, size first).  */
!           sz = 2;
!           bfd_putl16 (tdata->mhd_size, blk);
!         }
!       mhd = (struct vms_mhd *)(blk + sz);
        memset (mhd, 0, sizeof (struct vms_mhd));
        mhd->lbrflag = 0;
        mhd->id = MHD__C_MHDID;
***************
*** 1901,1931 ****
        bfd_putl32 (modules[i].ref, mhd->refcnt);
        /* FIXME: datim.  */
  
!       sz = (2 + sizeof (struct vms_mhd) + 1) & ~1;
!       if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
!         goto input_err;
  
        if (bfd_seek (current, 0, SEEK_SET) != 0)
          goto input_err;
  
!       while (1)
! 	{
!           sz = bfd_bread (blk, sizeof (blk), current);
!           if (sz == 0)
!             break;
            if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
              goto input_err;
          }
-       if (vms_write_data_block (arch, &data, &off,
-                                 eotdesc, sizeof (eotdesc), 1) < 0)
-         goto input_err;
      }
  
    /* Write the indexes.  */
    vbn = 2;
!   if (vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn) != TRUE)
      return FALSE;
!   if (vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn) != TRUE)
      return FALSE;
  
    /* Write libary header.  */
--- 2076,2174 ----
        bfd_putl32 (modules[i].ref, mhd->refcnt);
        /* FIXME: datim.  */
  
!       sz += tdata->mhd_size;
!       sz = (sz + 1) & ~1;
  
+       /* Rewind the member to be put into the archive.  */
        if (bfd_seek (current, 0, SEEK_SET) != 0)
          goto input_err;
  
!       /* Copy the member into the archive.  */
!       if (is_elfidx)
!         {
!           unsigned int modsize = 0;
!           bfd_size_type amt;
!           file_ptr off_hdr = off;
! 
!           /* Read to complete the first block.  */
!           amt = bfd_bread (blk + sz, VMS_BLOCK_SIZE - sz, current);
!           if (amt == (bfd_size_type)-1)
!             goto input_err;
!           modsize = amt;
!           if (amt < VMS_BLOCK_SIZE - sz)
!             {
!               /* The member size is less than a block.  Pad the block.  */
!               memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt);
!             }
!           bfd_putl32 (modsize, mhd->modsize);
! 
!           /* Write the first block (which contains an mhd).  */
!           if (bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
!             goto input_err;
! 
!           if (amt == VMS_BLOCK_SIZE - sz)
!             {
!               /* Copy the remaining.  */
!               char buffer[DEFAULT_BUFFERSIZE];
! 
!               while (1)
!                 {
!                   amt = bfd_bread (buffer, sizeof (buffer), current);
!                   if (amt == (bfd_size_type)-1)
!                     goto input_err;
!                   if (amt == 0)
!                     break;
!                   modsize += amt;
!                   if (amt != sizeof (buffer))
!                     {
!                       /* Clear the padding.  */
!                       memset (buffer + amt, 0, sizeof (buffer) - amt);
!                       amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
!                     }
!                   if (bfd_bwrite (buffer, amt, arch) != amt)
!                     goto input_err;
!                   off += amt;
!                 }
! 
!               /* Now that the size is known, write the first block (again).  */
!               bfd_putl32 (modsize, mhd->modsize);
!               if (bfd_seek (arch, off_hdr, SEEK_SET) != 0
!                   || bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
!                 goto input_err;
!               if (bfd_seek (arch, off, SEEK_SET) != 0)
!                 goto input_err;
!             }
!         }
!       else
!         {
!           /* Write the MHD.  */
            if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
              goto input_err;
+ 
+           /* Write the member.  */
+           while (1)
+             {
+               sz = bfd_bread (blk, sizeof (blk), current);
+               if (sz == 0)
+                 break;
+               if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
+                 goto input_err;
+             }
+ 
+           /* Write the end of module marker.  */
+           if (vms_write_data_block (arch, &data, &off,
+                                     eotdesc, sizeof (eotdesc), 1) < 0)
+             goto input_err;
          }
      }
  
    /* Write the indexes.  */
    vbn = 2;
!   if (vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn,
!                        is_elfidx) != TRUE)
      return FALSE;
!   if (vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn,
!                        is_elfidx) != TRUE)
      return FALSE;
  
    /* Write libary header.  */
***************
*** 1934,1946 ****
      struct vms_lhd *lhd = (struct vms_lhd *)blk;
      struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
      unsigned int idd_flags;
  
      memset (blk, 0, sizeof (blk));
  
!     lhd->type = LBR__C_TYP_EOBJ;
      lhd->nindex = 2;
!     bfd_putl32 (LHD_SANEID3, lhd->sanity);
!     bfd_putl16 (3, lhd->majorid);
      bfd_putl16 (0, lhd->minorid);
      snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
                "GNU ar %u.%u.%u",
--- 2177,2201 ----
      struct vms_lhd *lhd = (struct vms_lhd *)blk;
      struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
      unsigned int idd_flags;
+     unsigned int saneid;
  
      memset (blk, 0, sizeof (blk));
  
!     lhd->type = tdata->type;
      lhd->nindex = 2;
!     switch (tdata->kind)
!       {
!       case vms_lib_alpha:
!         saneid = LHD_SANEID3;
!         break;
!       case vms_lib_ia64:
!         saneid = LHD_SANEID6;
!         break;
!       default:
!         abort ();
!       }
!     bfd_putl32 (saneid, lhd->sanity);
!     bfd_putl16 (tdata->ver, lhd->majorid);
      bfd_putl16 (0, lhd->minorid);
      snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
                "GNU ar %u.%u.%u",
***************
*** 1950,1960 ****
      lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
      lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
  
!     /* FIXME.  */
!     bfd_putl64 (0, lhd->credat);
!     bfd_putl64 (0, lhd->updtim);
  
!     lhd->mhdusz = sizeof (struct vms_mhd) - MHD__C_USRDAT;
  
      bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
      bfd_putl32 (nbr_modules, lhd->modcnt);
--- 2205,2215 ----
      lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
      lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
  
!     bfd_putl32 (tdata->credat_lo, lhd->credat + 0);
!     bfd_putl32 (tdata->credat_hi, lhd->credat + 4);
!     vms_raw_get_time (lhd->updtim);
  
!     lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT;
  
      bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
      bfd_putl32 (nbr_modules, lhd->modcnt);
***************
*** 1977,1985 ****
      bfd_putl16 (sym_idx_vbn, idd->vbn);
      idd++;
  
!     if (bfd_seek (arch, 0, SEEK_SET) != 0)
!       return FALSE;
!     if (bfd_bwrite (blk, sizeof (blk), arch) != sizeof (blk))
        return FALSE;
    }
  
--- 2232,2238 ----
      bfd_putl16 (sym_idx_vbn, idd->vbn);
      idd++;
  
!     if (vms_write_block (arch, 1, blk) != TRUE)
        return FALSE;
    }
  



More information about the Binutils mailing list