Home | History | Annotate | Line # | Download | only in bfd
      1 /* BFD back-end for VMS archive files.
      2 
      3    Copyright (C) 2010-2025 Free Software Foundation, Inc.
      4    Written by Tristan Gingold <gingold (at) adacore.com>, AdaCore.
      5 
      6    This file is part of BFD, the Binary File Descriptor library.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 #include "libbfd.h"
     26 #include "safe-ctype.h"
     27 #include "bfdver.h"
     28 #include "libiberty.h"
     29 #include "vms.h"
     30 #include "vms/lbr.h"
     31 #include "vms/dcx.h"
     32 
     33 /* The standard VMS disk block size.  */
     34 #ifndef VMS_BLOCK_SIZE
     35 #define VMS_BLOCK_SIZE 512
     36 #endif
     37 
     38 /* Maximum key length (which is also the maximum symbol length in archive).  */
     39 #define MAX_KEYLEN 128
     40 #define MAX_EKEYLEN 1024
     41 
     42 /* DCX Submaps.  */
     43 
     44 struct dcxsbm_desc
     45 {
     46   unsigned char min_char;
     47   unsigned char max_char;
     48   unsigned char *flags;
     49   unsigned char *nodes;
     50   unsigned short *next;
     51 };
     52 
     53 /* Kind of library.  Used to filter in archive_p.  */
     54 
     55 enum vms_lib_kind
     56   {
     57     vms_lib_vax,
     58     vms_lib_alpha,
     59     vms_lib_ia64,
     60     vms_lib_txt
     61   };
     62 
     63 /* Back-end private data.  */
     64 
     65 struct lib_tdata
     66 {
     67   /* Standard tdata for an archive.  But we don't use many fields.  */
     68   struct artdata artdata;
     69 
     70   /* Major version.  */
     71   unsigned char ver;
     72 
     73   /* Type of the archive.  */
     74   unsigned char type;
     75 
     76   /* Kind of archive.  Summary of its type.  */
     77   enum vms_lib_kind kind;
     78 
     79   /* Total size of the mhd (element header).  */
     80   unsigned int mhd_size;
     81 
     82   /* Creation date.  */
     83   unsigned int credat_lo;
     84   unsigned int credat_hi;
     85 
     86   /* Vector of modules (archive elements), already sorted.  */
     87   unsigned int nbr_modules;
     88   struct carsym *modules;
     89   bfd **cache;
     90 
     91   /* DCX (decompression) data.  */
     92   unsigned int nbr_dcxsbm;
     93   struct dcxsbm_desc *dcxsbm;
     94 };
     95 
     96 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
     97 
     98 /* End-Of-Text pattern.  This is a special record to mark the end of file.  */
     99 
    100 static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
    101 
    102 /* Describe the current state of carsym entries while building the archive
    103    table of content.  Things are simple with Alpha archives as the number
    104    of entries is known, but with IA64 archives a entry can make a reference
    105    to severals members.  Therefore we must be able to extend the table on the
    106    fly, but it should be allocated on the bfd - which doesn't support realloc.
    107    To reduce the overhead, the table is initially allocated in the BFD's
    108    objalloc and extended if necessary on the heap.  In the later case, it
    109    is finally copied to the BFD's objalloc so that it will automatically be
    110    freed.  */
    111 
    112 struct carsym_mem
    113 {
    114   /* The table of content.  */
    115   struct carsym *idx;
    116 
    117   /* Number of entries used in the table.  */
    118   unsigned int nbr;
    119 
    120   /* Maximum number of entries.  */
    121   unsigned int max;
    122 
    123   /* Do not allocate more that this number of entries.  */
    124   unsigned int limit;
    125 
    126   /* If true, the table was reallocated on the heap.  If false, it is still
    127      in the BFD's objalloc.  */
    128   bool realloced;
    129 };
    130 
    131 /* Simply add a name to the index.  */
    132 
    133 static bool
    134 vms_add_index (struct carsym_mem *cs, char *name,
    135 	       unsigned int idx_vbn, unsigned int idx_off)
    136 {
    137   if (cs->nbr == cs->max)
    138     {
    139       struct carsym *n;
    140       size_t amt;
    141 
    142       if (cs->max > -33u / 2 || cs->max >= cs->limit)
    143 	{
    144 	  bfd_set_error (bfd_error_file_too_big);
    145 	  return false;
    146 	}
    147       cs->max = 2 * cs->max + 32;
    148       if (cs->max > cs->limit)
    149 	cs->max = cs->limit;
    150       if (_bfd_mul_overflow (cs->max, sizeof (struct carsym), &amt))
    151 	{
    152 	  bfd_set_error (bfd_error_file_too_big);
    153 	  return false;
    154 	}
    155 
    156       if (!cs->realloced)
    157 	{
    158 	  n = bfd_malloc (amt);
    159 	  if (n == NULL)
    160 	    return false;
    161 	  memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym));
    162 	  /* And unfortunately we can't free cs->idx.  */
    163 	}
    164       else
    165 	{
    166 	  n = bfd_realloc_or_free (cs->idx, amt);
    167 	  if (n == NULL)
    168 	    return false;
    169 	}
    170       cs->idx = n;
    171       cs->realloced = true;
    172     }
    173   cs->idx[cs->nbr].file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
    174   cs->idx[cs->nbr].name = name;
    175   cs->nbr++;
    176   return true;
    177 }
    178 
    179 /* Follow all member of a lns list (pointed by RFA) and add indexes for
    180    NAME.  Return FALSE in case of error.  */
    181 
    182 static bool
    183 vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
    184 			   struct vms_rfa *rfa)
    185 {
    186   struct vms_lns lns;
    187   unsigned int vbn;
    188   file_ptr off;
    189 
    190   while (1)
    191     {
    192       vbn = bfd_getl32 (rfa->vbn);
    193       if (vbn == 0)
    194 	return true;
    195 
    196       /* Read the LHS.  */
    197       off = (vbn - 1) * VMS_BLOCK_SIZE + bfd_getl16 (rfa->offset);
    198       if (bfd_seek (abfd, off, SEEK_SET) != 0
    199 	  || bfd_read (&lns, sizeof (lns), abfd) != sizeof (lns))
    200 	return false;
    201 
    202       if (!vms_add_index (cs, name,
    203 			  bfd_getl32 (lns.modrfa.vbn),
    204 			  bfd_getl16 (lns.modrfa.offset)))
    205 	return false;
    206 
    207       rfa = &lns.nxtrfa;
    208     }
    209 }
    210 
    211 /* Read block VBN from ABFD and store it into BLK.  Return FALSE in case of error.  */
    212 
    213 static bool
    214 vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
    215 {
    216   file_ptr off;
    217 
    218   off = (vbn - 1) * VMS_BLOCK_SIZE;
    219   if (bfd_seek (abfd, off, SEEK_SET) != 0
    220       || bfd_read (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE)
    221     return false;
    222 
    223   return true;
    224 }
    225 
    226 /* Write the content of BLK to block VBN of ABFD.  Return FALSE in case of error.  */
    227 
    228 static bool
    229 vms_write_block (bfd *abfd, unsigned int vbn, void *blk)
    230 {
    231   file_ptr off;
    232 
    233   off = (vbn - 1) * VMS_BLOCK_SIZE;
    234   if (bfd_seek (abfd, off, SEEK_SET) != 0
    235       || bfd_write (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE)
    236     return false;
    237 
    238   return true;
    239 }
    240 
    241 /* Read index block VBN and put the entry in **IDX (which is updated).
    242    If the entry is indirect, recurse.  */
    243 
    244 static bool
    245 vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs,
    246 		    unsigned int recur_count)
    247 {
    248   struct vms_indexdef indexdef;
    249   file_ptr off;
    250   unsigned char *p;
    251   unsigned char *endp;
    252   unsigned int n;
    253 
    254   if (recur_count == 100)
    255     {
    256       bfd_set_error (bfd_error_bad_value);
    257       return false;
    258     }
    259 
    260   /* Read the index block.  */
    261   BFD_ASSERT (sizeof (indexdef) == VMS_BLOCK_SIZE);
    262   if (!vms_read_block (abfd, vbn, &indexdef))
    263     return false;
    264 
    265   /* Traverse it.  */
    266   p = &indexdef.keys[0];
    267   n = bfd_getl16 (indexdef.used);
    268   if (n > sizeof (indexdef.keys))
    269     return false;
    270   endp = p + n;
    271   while (p < endp)
    272     {
    273       unsigned int idx_vbn;
    274       unsigned int idx_off;
    275       unsigned int keylen;
    276       unsigned char *keyname;
    277       unsigned int flags;
    278 
    279       /* Extract key length.  */
    280       if (bfd_libdata (abfd)->ver == LBR_MAJORID
    281 	  && offsetof (struct vms_idx, keyname) <= (size_t) (endp - p))
    282 	{
    283 	  struct vms_idx *ridx = (struct vms_idx *)p;
    284 
    285 	  idx_vbn = bfd_getl32 (ridx->rfa.vbn);
    286 	  idx_off = bfd_getl16 (ridx->rfa.offset);
    287 
    288 	  keylen = ridx->keylen;
    289 	  flags = 0;
    290 	  keyname = ridx->keyname;
    291 	}
    292       else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID
    293 	       && offsetof (struct vms_elfidx, keyname) <= (size_t) (endp - p))
    294 	{
    295 	  struct vms_elfidx *ridx = (struct vms_elfidx *)p;
    296 
    297 	  idx_vbn = bfd_getl32 (ridx->rfa.vbn);
    298 	  idx_off = bfd_getl16 (ridx->rfa.offset);
    299 
    300 	  keylen = bfd_getl16 (ridx->keylen);
    301 	  flags = ridx->flags;
    302 	  keyname = ridx->keyname;
    303 	}
    304       else
    305 	return false;
    306 
    307       /* Illegal value.  */
    308       if (idx_vbn == 0)
    309 	return false;
    310 
    311       /* Point to the next index entry.  */
    312       p = keyname + keylen;
    313       if (p > endp)
    314 	return false;
    315 
    316       if (idx_off == RFADEF__C_INDEX)
    317 	{
    318 	  /* Indirect entry.  Recurse.  */
    319 	  if (!vms_traverse_index (abfd, idx_vbn, cs, recur_count + 1))
    320 	    return false;
    321 	}
    322       else
    323 	{
    324 	  /* Add a new entry.  */
    325 	  char *name;
    326 
    327 	  if (flags & ELFIDX__SYMESC)
    328 	    {
    329 	      /* Extended key name.  */
    330 	      unsigned int noff = 0;
    331 	      unsigned int koff;
    332 	      unsigned int kvbn;
    333 	      struct vms_kbn *kbn;
    334 	      unsigned char kblk[VMS_BLOCK_SIZE];
    335 
    336 	      /* Sanity check.  */
    337 	      if (keylen != sizeof (struct vms_kbn))
    338 		return false;
    339 
    340 	      kbn = (struct vms_kbn *)keyname;
    341 	      keylen = bfd_getl16 (kbn->keylen);
    342 
    343 	      name = bfd_alloc (abfd, keylen + 1);
    344 	      if (name == NULL)
    345 		return false;
    346 	      kvbn = bfd_getl32 (kbn->rfa.vbn);
    347 	      koff = bfd_getl16 (kbn->rfa.offset);
    348 
    349 	      /* Read the key, chunk by chunk.  */
    350 	      do
    351 		{
    352 		  unsigned int klen;
    353 
    354 		  if (!vms_read_block (abfd, kvbn, kblk))
    355 		    return false;
    356 		  if (koff > sizeof (kblk) - sizeof (struct vms_kbn))
    357 		    return false;
    358 		  kbn = (struct vms_kbn *)(kblk + koff);
    359 		  klen = bfd_getl16 (kbn->keylen);
    360 		  if (klen > sizeof (kblk) - sizeof (struct vms_kbn) - koff)
    361 		    return false;
    362 		  kvbn = bfd_getl32 (kbn->rfa.vbn);
    363 		  koff = bfd_getl16 (kbn->rfa.offset);
    364 
    365 		  if (noff + klen > keylen)
    366 		    return false;
    367 		  memcpy (name + noff, kbn + 1, klen);
    368 		  noff += klen;
    369 		}
    370 	      while (kvbn != 0);
    371 
    372 	      /* Sanity check.  */
    373 	      if (noff != keylen)
    374 		return false;
    375 	    }
    376 	  else
    377 	    {
    378 	      /* Usual key name.  */
    379 	      name = bfd_alloc (abfd, keylen + 1);
    380 	      if (name == NULL)
    381 		return false;
    382 
    383 	      memcpy (name, keyname, keylen);
    384 	    }
    385 	  name[keylen] = 0;
    386 
    387 	  if (flags & ELFIDX__LISTRFA)
    388 	    {
    389 	      struct vms_lhs lhs;
    390 
    391 	      /* Read the LHS.  */
    392 	      off = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
    393 	      if (bfd_seek (abfd, off, SEEK_SET) != 0
    394 		  || bfd_read (&lhs, sizeof (lhs), abfd) != sizeof (lhs))
    395 		return false;
    396 
    397 	      /* These extra entries may cause reallocation of CS.  */
    398 	      if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_g_rfa))
    399 		return false;
    400 	      if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_wk_rfa))
    401 		return false;
    402 	      if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_g_rfa))
    403 		return false;
    404 	      if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_wk_rfa))
    405 		return false;
    406 	    }
    407 	  else
    408 	    {
    409 	      if (!vms_add_index (cs, name, idx_vbn, idx_off))
    410 		return false;
    411 	    }
    412 	}
    413     }
    414 
    415   return true;
    416 }
    417 
    418 /* Read index #IDX, which must have NBREL entries.  */
    419 
    420 static struct carsym *
    421 vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
    422 {
    423   struct vms_idd idd;
    424   unsigned int flags;
    425   unsigned int vbn;
    426   ufile_ptr filesize;
    427   size_t amt;
    428   struct carsym *csbuf;
    429   struct carsym_mem csm;
    430 
    431   /* Read index desription.  */
    432   if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0
    433       || bfd_read (&idd, sizeof (idd), abfd) != sizeof (idd))
    434     return NULL;
    435 
    436   /* Sanity checks.  */
    437   flags = bfd_getl16 (idd.flags);
    438   if (!(flags & IDD__FLAGS_ASCII)
    439       || !(flags & IDD__FLAGS_VARLENIDX))
    440     return NULL;
    441 
    442   filesize = bfd_get_file_size (abfd);
    443   csm.nbr = 0;
    444   csm.max = *nbrel;
    445   csm.limit = -1u;
    446   csm.realloced = false;
    447   if (filesize != 0)
    448     {
    449       /* Put an upper bound based on a file full of single char keys.
    450 	 This is to prevent fuzzed binary silliness.  It is easily
    451 	 possible to set up loops over file blocks that add syms
    452 	 without end.  */
    453       if (filesize / (sizeof (struct vms_rfa) + 2) <= -1u)
    454 	csm.limit = filesize / (sizeof (struct vms_rfa) + 2);
    455     }
    456   if (csm.max > csm.limit)
    457     csm.max = csm.limit;
    458   if (_bfd_mul_overflow (csm.max, sizeof (struct carsym), &amt))
    459     return NULL;
    460   csm.idx = csbuf = bfd_alloc (abfd, amt);
    461   if (csm.idx == NULL)
    462     return NULL;
    463 
    464   /* Note: if the index is empty, there is no block to traverse.  */
    465   vbn = bfd_getl32 (idd.vbn);
    466   if (vbn != 0 && !vms_traverse_index (abfd, vbn, &csm, 0))
    467     {
    468       if (csm.realloced)
    469 	free (csm.idx);
    470 
    471       /* Note: in case of error, we can free what was allocated on the
    472 	 BFD's objalloc.  */
    473       bfd_release (abfd, csbuf);
    474       return NULL;
    475     }
    476 
    477   if (csm.realloced)
    478     {
    479       /* There are more entries than the first estimate.  Allocate on
    480 	 the BFD's objalloc.  */
    481       csbuf = bfd_alloc (abfd, csm.nbr * sizeof (struct carsym));
    482       if (csbuf == NULL)
    483 	{
    484 	  free (csm.idx);
    485 	  return NULL;
    486 	}
    487       memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym));
    488       free (csm.idx);
    489       csm.idx = csbuf;
    490     }
    491   *nbrel = csm.nbr;
    492   return csm.idx;
    493 }
    494 
    495 /* Standard function.  */
    496 
    497 static bfd_cleanup
    498 _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
    499 {
    500   struct vms_lhd lhd;
    501   unsigned int sanity;
    502   unsigned int majorid;
    503   struct lib_tdata *tdata_hold;
    504   struct lib_tdata *tdata;
    505   unsigned int dcxvbn;
    506   unsigned int nbr_ent;
    507 
    508   /* Read header.  */
    509   if (bfd_read (&lhd, sizeof (lhd), abfd) != sizeof (lhd))
    510     {
    511       if (bfd_get_error () != bfd_error_system_call)
    512 	bfd_set_error (bfd_error_wrong_format);
    513       return NULL;
    514     }
    515 
    516   /* Check sanity (= magic) number.  */
    517   sanity = bfd_getl32 (lhd.sanity);
    518   if (!(sanity == LHD_SANEID3
    519 	|| sanity == LHD_SANEID6
    520 	|| sanity == LHD_SANEID_DCX))
    521     {
    522       bfd_set_error (bfd_error_wrong_format);
    523       return NULL;
    524     }
    525   majorid = bfd_getl32 (lhd.majorid);
    526 
    527   /* Check archive kind.  */
    528   switch (kind)
    529     {
    530     case vms_lib_alpha:
    531       if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB)
    532 	  || majorid != LBR_MAJORID
    533 	  || lhd.nindex != 2)
    534 	{
    535 	  bfd_set_error (bfd_error_wrong_format);
    536 	  return NULL;
    537 	}
    538       break;
    539     case vms_lib_ia64:
    540       if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB)
    541 	  || majorid != LBR_ELFMAJORID
    542 	  || lhd.nindex != 2)
    543 	{
    544 	  bfd_set_error (bfd_error_wrong_format);
    545 	  return NULL;
    546 	}
    547       break;
    548     case vms_lib_txt:
    549       if ((lhd.type != LBR__C_TYP_TXT
    550 	   && lhd.type != LBR__C_TYP_MLB
    551 	   && lhd.type != LBR__C_TYP_HLP)
    552 	  || majorid != LBR_MAJORID
    553 	  || lhd.nindex != 1)
    554 	{
    555 	  bfd_set_error (bfd_error_wrong_format);
    556 	  return NULL;
    557 	}
    558       break;
    559     default:
    560       abort ();
    561     }
    562 
    563   /* Allocate and initialize private data.  */
    564   tdata_hold = bfd_libdata (abfd);
    565   tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
    566   if (tdata == NULL)
    567     return NULL;
    568   abfd->tdata.any = (void *)tdata;
    569   tdata->ver = majorid;
    570   tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz;
    571   tdata->type = lhd.type;
    572   tdata->kind = kind;
    573   tdata->credat_lo = bfd_getl32 (lhd.credat + 0);
    574   tdata->credat_hi = bfd_getl32 (lhd.credat + 4);
    575 
    576   /* Read indexes.  */
    577   tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
    578   tdata->artdata.symdef_count = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules;
    579   nbr_ent = tdata->nbr_modules;
    580   tdata->modules = vms_lib_read_index (abfd, 0, &nbr_ent);
    581   if (tdata->modules == NULL || nbr_ent != tdata->nbr_modules)
    582     goto err;
    583   if (lhd.nindex == 2)
    584     {
    585       nbr_ent = tdata->artdata.symdef_count;
    586       tdata->artdata.symdefs = vms_lib_read_index (abfd, 1, &nbr_ent);
    587       if (tdata->artdata.symdefs == NULL)
    588 	goto err;
    589       /* Only IA64 archives may have more entries in the index that what
    590 	 was declared.  */
    591       if (nbr_ent != tdata->artdata.symdef_count
    592 	  && kind != vms_lib_ia64)
    593 	goto err;
    594       tdata->artdata.symdef_count = nbr_ent;
    595     }
    596   tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
    597   if (tdata->cache == NULL)
    598     goto err;
    599 
    600   /* Read DCX submaps.  */
    601   dcxvbn = bfd_getl32 (lhd.dcxmapvbn);
    602   if (dcxvbn != 0)
    603     {
    604       unsigned char buf_reclen[4];
    605       unsigned int reclen;
    606       unsigned char *buf;
    607       struct vms_dcxmap *map;
    608       unsigned int sbm_off;
    609       unsigned int i;
    610 
    611       if (bfd_seek (abfd, (dcxvbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) != 0
    612 	  || bfd_read (buf_reclen, sizeof (buf_reclen), abfd)
    613 	  != sizeof (buf_reclen))
    614 	goto err;
    615       reclen = bfd_getl32 (buf_reclen);
    616       if (reclen < sizeof (struct vms_dcxmap))
    617 	goto err;
    618       buf = _bfd_malloc_and_read (abfd, reclen, reclen);
    619       if (buf == NULL)
    620 	goto err;
    621       map = (struct vms_dcxmap *)buf;
    622       tdata->nbr_dcxsbm = bfd_getl16 (map->nsubs);
    623       sbm_off = bfd_getl16 (map->sub0);
    624       tdata->dcxsbm = (struct dcxsbm_desc *)bfd_alloc
    625 	(abfd, tdata->nbr_dcxsbm * sizeof (struct dcxsbm_desc));
    626       for (i = 0; i < tdata->nbr_dcxsbm; i++)
    627 	{
    628 	  struct vms_dcxsbm *sbm;
    629 	  struct dcxsbm_desc *sbmdesc = &tdata->dcxsbm[i];
    630 	  unsigned int sbm_len;
    631 	  unsigned int sbm_sz;
    632 	  unsigned int off;
    633 	  unsigned char *buf1;
    634 	  unsigned int l, j;
    635 
    636 	  if (sbm_off > reclen
    637 	      || reclen - sbm_off < sizeof (struct vms_dcxsbm))
    638 	    {
    639 	    err_free_buf:
    640 	      free (buf);
    641 	      goto err;
    642 	    }
    643 	  sbm = (struct vms_dcxsbm *) (buf + sbm_off);
    644 	  sbm_sz = bfd_getl16 (sbm->size);
    645 	  sbm_off += sbm_sz;
    646 	  if (sbm_off > reclen)
    647 	    goto err_free_buf;
    648 
    649 	  sbmdesc->min_char = sbm->min_char;
    650 	  BFD_ASSERT (sbmdesc->min_char == 0);
    651 	  sbmdesc->max_char = sbm->max_char;
    652 	  sbm_len = sbmdesc->max_char - sbmdesc->min_char + 1;
    653 	  l = (2 * sbm_len + 7) / 8;
    654 	  if (sbm_sz < sizeof (struct vms_dcxsbm) + l + sbm_len
    655 	      || (tdata->nbr_dcxsbm > 1
    656 		  && sbm_sz < sizeof (struct vms_dcxsbm) + l + 3 * sbm_len))
    657 	    goto err_free_buf;
    658 	  sbmdesc->flags = (unsigned char *)bfd_alloc (abfd, l);
    659 	  off = bfd_getl16 (sbm->flags);
    660 	  if (off > sbm_sz
    661 	      || sbm_sz - off < l)
    662 	    goto err_free_buf;
    663 	  memcpy (sbmdesc->flags, (bfd_byte *) sbm + off, l);
    664 	  sbmdesc->nodes = (unsigned char *)bfd_alloc (abfd, 2 * sbm_len);
    665 	  off = bfd_getl16 (sbm->nodes);
    666 	  if (off > sbm_sz
    667 	      || sbm_sz - off < 2 * sbm_len)
    668 	    goto err_free_buf;
    669 	  memcpy (sbmdesc->nodes, (bfd_byte *) sbm + off, 2 * sbm_len);
    670 	  off = bfd_getl16 (sbm->next);
    671 	  if (off != 0)
    672 	    {
    673 	      if (off > sbm_sz
    674 		  || sbm_sz - off < 2 * sbm_len)
    675 		goto err_free_buf;
    676 	      /* Read the 'next' array.  */
    677 	      sbmdesc->next = (unsigned short *) bfd_alloc (abfd, 2 * sbm_len);
    678 	      buf1 = (bfd_byte *) sbm + off;
    679 	      for (j = 0; j < sbm_len; j++)
    680 		sbmdesc->next[j] = bfd_getl16 (buf1 + j * 2);
    681 	    }
    682 	  else
    683 	    {
    684 	      /* There is no next array if there is only one submap.  */
    685 	      BFD_ASSERT (tdata->nbr_dcxsbm == 1);
    686 	      sbmdesc->next = NULL;
    687 	    }
    688 	}
    689       free (buf);
    690     }
    691   else
    692     {
    693       tdata->nbr_dcxsbm = 0;
    694     }
    695 
    696   /* The map is always present.  Also mark shared image library.  */
    697   abfd->has_armap = true;
    698   if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB)
    699     abfd->is_thin_archive = true;
    700 
    701   return _bfd_no_cleanup;
    702 
    703  err:
    704   bfd_release (abfd, tdata);
    705   abfd->tdata.any = (void *)tdata_hold;
    706   return NULL;
    707 }
    708 
    709 /* Standard function for alpha libraries.  */
    710 
    711 bfd_cleanup
    712 _bfd_vms_lib_alpha_archive_p (bfd *abfd)
    713 {
    714   return _bfd_vms_lib_archive_p (abfd, vms_lib_alpha);
    715 }
    716 
    717 /* Standard function for ia64 libraries.  */
    718 
    719 bfd_cleanup
    720 _bfd_vms_lib_ia64_archive_p (bfd *abfd)
    721 {
    722   return _bfd_vms_lib_archive_p (abfd, vms_lib_ia64);
    723 }
    724 
    725 /* Standard function for text libraries.  */
    726 
    727 static bfd_cleanup
    728 _bfd_vms_lib_txt_archive_p (bfd *abfd)
    729 {
    730   return _bfd_vms_lib_archive_p (abfd, vms_lib_txt);
    731 }
    732 
    733 /* Standard bfd function.  */
    734 
    735 static bool
    736 _bfd_vms_lib_mkarchive (bfd *abfd, enum vms_lib_kind kind)
    737 {
    738   struct lib_tdata *tdata;
    739 
    740   tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
    741   if (tdata == NULL)
    742     return false;
    743 
    744   abfd->tdata.any = (void *)tdata;
    745   vms_get_time (&tdata->credat_hi, &tdata->credat_lo);
    746 
    747   tdata->kind = kind;
    748   switch (kind)
    749     {
    750     case vms_lib_alpha:
    751       tdata->ver = LBR_MAJORID;
    752       tdata->mhd_size = offsetof (struct vms_mhd, pad1);
    753       tdata->type = LBR__C_TYP_EOBJ;
    754       break;
    755     case vms_lib_ia64:
    756       tdata->ver = LBR_ELFMAJORID;
    757       tdata->mhd_size = sizeof (struct vms_mhd);
    758       tdata->type = LBR__C_TYP_IOBJ;
    759       break;
    760     default:
    761       abort ();
    762     }
    763 
    764   tdata->nbr_modules = 0;
    765   tdata->artdata.symdef_count = 0;
    766   tdata->modules = NULL;
    767   tdata->artdata.symdefs = NULL;
    768   tdata->cache = NULL;
    769 
    770   return true;
    771 }
    772 
    773 bool
    774 _bfd_vms_lib_alpha_mkarchive (bfd *abfd)
    775 {
    776   return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha);
    777 }
    778 
    779 bool
    780 _bfd_vms_lib_ia64_mkarchive (bfd *abfd)
    781 {
    782   return _bfd_vms_lib_mkarchive (abfd, vms_lib_ia64);
    783 }
    784 
    785 /* Find NAME in the symbol index.  Return the index.  */
    786 
    787 symindex
    788 _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
    789 {
    790   struct lib_tdata *tdata = bfd_libdata (abfd);
    791   carsym *syms = tdata->artdata.symdefs;
    792   int lo, hi;
    793 
    794   /* Open-coded binary search for speed.  */
    795   lo = 0;
    796   hi = tdata->artdata.symdef_count - 1;
    797 
    798   while (lo <= hi)
    799     {
    800       int mid = lo + (hi - lo) / 2;
    801       int diff;
    802 
    803       diff = (char)(name[0] - syms[mid].name[0]);
    804       if (diff == 0)
    805 	diff = strcmp (name, syms[mid].name);
    806       if (diff == 0)
    807 	return mid;
    808       else if (diff < 0)
    809 	hi = mid - 1;
    810       else
    811 	lo = mid + 1;
    812     }
    813   return BFD_NO_MORE_SYMBOLS;
    814 }
    815 
    816 /* IO vector for archive member.  Need that because members are not linearly
    817    stored in archives.  */
    818 
    819 struct vms_lib_iovec
    820 {
    821   /* Current offset.  */
    822   ufile_ptr where;
    823 
    824   /* Length of the module, when known.  */
    825   ufile_ptr file_len;
    826 
    827   /* Current position in the record from bfd_read point of view (ie, after
    828      decompression).  0 means that no data byte have been read, -2 and -1
    829      are reserved for the length word.  */
    830   int rec_pos;
    831 #define REC_POS_NL   -4
    832 #define REC_POS_PAD  -3
    833 #define REC_POS_LEN0 -2
    834 #define REC_POS_LEN1 -1
    835 
    836   /* Record length.  */
    837   unsigned short rec_len;
    838   /* Number of bytes to read in the current record.  */
    839   unsigned short rec_rem;
    840   /* Offset of the next block.  */
    841   file_ptr next_block;
    842   /* Current *data* offset in the data block.  */
    843   unsigned short blk_off;
    844 
    845   /* Offset of the first block.  Extracted from the index.  */
    846   file_ptr first_block;
    847 
    848   /* Initial next_block.  Extracted when the MHD is read.  */
    849   file_ptr init_next_block;
    850   /* Initial blk_off, once the MHD is read.  */
    851   unsigned short init_blk_off;
    852 
    853   /* Used to store any 3 byte record, which could be the EOF pattern.  */
    854   unsigned char pattern[4];
    855 
    856   /* DCX.  */
    857   struct dcxsbm_desc *dcxsbms;
    858   /* Current submap.  */
    859   struct dcxsbm_desc *dcx_sbm;
    860   /* Current offset in the submap.  */
    861   unsigned int dcx_offset;
    862   int dcx_pos;
    863 
    864   /* Compressed buffer.  */
    865   unsigned char *dcx_buf;
    866   /* Size of the buffer.  Used to resize.  */
    867   unsigned int dcx_max;
    868   /* Number of valid bytes in the buffer.  */
    869   unsigned int dcx_rlen;
    870 };
    871 
    872 /* Return the current position.  */
    873 
    874 static file_ptr
    875 vms_lib_btell (struct bfd *abfd)
    876 {
    877   struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
    878   return vec->where;
    879 }
    880 
    881 /* Read the header of the next data block if all bytes of the current block
    882    have been read.  */
    883 
    884 static bool
    885 vms_lib_read_block (struct bfd *abfd)
    886 {
    887   struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
    888 
    889   if (vec->blk_off == DATA__LENGTH)
    890     {
    891       unsigned char hdr[DATA__DATA];
    892 
    893       /* Read next block.  */
    894       if (bfd_seek (abfd->my_archive, vec->next_block, SEEK_SET) != 0)
    895 	return false;
    896       if (bfd_read (hdr, sizeof (hdr), abfd->my_archive) != sizeof (hdr))
    897 	return false;
    898       vec->next_block = (bfd_getl32 (hdr + 2) - 1) * VMS_BLOCK_SIZE;
    899       vec->blk_off = sizeof (hdr);
    900     }
    901   return true;
    902 }
    903 
    904 /* Read NBYTES from ABFD into BUF if not NULL.  If BUF is NULL, bytes are
    905    not stored.  Read linearly from the library, but handle blocks.  This
    906    function does not handle records nor EOF.  */
    907 
    908 static file_ptr
    909 vms_lib_bread_raw (struct bfd *abfd, unsigned char *buf, file_ptr nbytes)
    910 {
    911   struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
    912   file_ptr res;
    913 
    914   res = 0;
    915   while (nbytes > 0)
    916     {
    917       unsigned int l;
    918 
    919       /* Be sure the current data block is read.  */
    920       if (!vms_lib_read_block (abfd))
    921 	return -1;
    922 
    923       /* Do not read past the data block, do not read more than requested.  */
    924       l = DATA__LENGTH - vec->blk_off;
    925       if (l > nbytes)
    926 	l = nbytes;
    927       if (l == 0)
    928 	return 0;
    929       if (buf != NULL)
    930 	{
    931 	  /* Really read into BUF.  */
    932 	  if (bfd_read (buf, l, abfd->my_archive) != l)
    933 	    return -1;
    934 	}
    935       else
    936 	{
    937 	  /* Make as if we are reading.  */
    938 	  if (bfd_seek (abfd->my_archive, l, SEEK_CUR) != 0)
    939 	    return -1;
    940 	}
    941 
    942       if (buf != NULL)
    943 	buf += l;
    944       vec->blk_off += l;
    945       nbytes -= l;
    946       res += l;
    947     }
    948   return res;
    949 }
    950 
    951 /* Decompress NBYTES from VEC.  Store the bytes into BUF if not NULL.  */
    952 
    953 static file_ptr
    954 vms_lib_dcx (struct vms_lib_iovec *vec, unsigned char *buf, file_ptr nbytes)
    955 {
    956   struct dcxsbm_desc *sbm;
    957   unsigned int i;
    958   unsigned int offset;
    959   unsigned int j;
    960   file_ptr res = 0;
    961 
    962   /* The loop below expect to deliver at least one byte.  */
    963   if (nbytes == 0)
    964     return 0;
    965 
    966   /* Get the current state.  */
    967   sbm = vec->dcx_sbm;
    968   offset = vec->dcx_offset;
    969   j = vec->dcx_pos & 7;
    970 
    971   for (i = vec->dcx_pos >> 3; i < vec->dcx_rlen; i++)
    972     {
    973       unsigned char b = vec->dcx_buf[i];
    974 
    975       for (; j < 8; j++)
    976 	{
    977 	  if (b & (1 << j))
    978 	    offset++;
    979 	  if (!(sbm->flags[offset >> 3] & (1 << (offset & 7))))
    980 	    {
    981 	      unsigned int n_offset = sbm->nodes[offset];
    982 	      if (n_offset == 0)
    983 		{
    984 		  /* End of buffer.  Stay where we are.  */
    985 		  vec->dcx_pos = (i << 3) + j;
    986 		  if (b & (1 << j))
    987 		    offset--;
    988 		  vec->dcx_offset = offset;
    989 		  vec->dcx_sbm = sbm;
    990 		  return res;
    991 		}
    992 	      offset = 2 * n_offset;
    993 	    }
    994 	  else
    995 	    {
    996 	      unsigned char v = sbm->nodes[offset];
    997 
    998 	      if (sbm->next != NULL)
    999 		sbm = vec->dcxsbms + sbm->next[v];
   1000 	      offset = 0;
   1001 	      res++;
   1002 
   1003 	      if (buf)
   1004 		{
   1005 		  *buf++ = v;
   1006 		  nbytes--;
   1007 
   1008 		  if (nbytes == 0)
   1009 		    {
   1010 		      vec->dcx_pos = (i << 3) + j + 1;
   1011 		      vec->dcx_offset = offset;
   1012 		      vec->dcx_sbm = sbm;
   1013 
   1014 		      return res;
   1015 		    }
   1016 		}
   1017 	    }
   1018 	}
   1019       j = 0;
   1020     }
   1021   return -1;
   1022 }
   1023 
   1024 /* Standard IOVEC function.  */
   1025 
   1026 static file_ptr
   1027 vms_lib_bread (struct bfd *abfd, void *vbuf, file_ptr nbytes)
   1028 {
   1029   struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
   1030   file_ptr res;
   1031   file_ptr chunk;
   1032   unsigned char *buf = (unsigned char *)vbuf;
   1033 
   1034   /* Do not read past the end.  */
   1035   if (vec->where >= vec->file_len)
   1036     return 0;
   1037 
   1038   res = 0;
   1039   while (nbytes > 0)
   1040     {
   1041       if (vec->rec_rem == 0)
   1042 	{
   1043 	  unsigned char blen[2];
   1044 
   1045 	  /* Read record length.  */
   1046 	  if (vms_lib_bread_raw (abfd, blen, sizeof (blen)) != sizeof (blen))
   1047 	    return -1;
   1048 	  vec->rec_len = bfd_getl16 (blen);
   1049 	  if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
   1050 	    {
   1051 	      /* Discard record size and align byte.  */
   1052 	      vec->rec_pos = 0;
   1053 	      vec->rec_rem = vec->rec_len;
   1054 	    }
   1055 	  else
   1056 	    {
   1057 	      /* Prepend record size.  */
   1058 	      vec->rec_pos = REC_POS_LEN0;
   1059 	      vec->rec_rem = (vec->rec_len + 1) & ~1;	/* With align byte.  */
   1060 	    }
   1061 	  if (vec->rec_len == 3)
   1062 	    {
   1063 	      /* Possibly end of file.  Check the pattern.  */
   1064 	      if (vms_lib_bread_raw (abfd, vec->pattern, 4) != 4)
   1065 		return -1;
   1066 	      if (!memcmp (vec->pattern, eotdesc + 2, 3))
   1067 		{
   1068 		  /* This is really an EOF.  */
   1069 		  vec->where += res;
   1070 		  vec->file_len = vec->where;
   1071 		  return res;
   1072 		}
   1073 	    }
   1074 
   1075 	  if (vec->dcxsbms != NULL)
   1076 	    {
   1077 	      /* This is a compressed member.  */
   1078 	      unsigned int len;
   1079 	      file_ptr elen;
   1080 
   1081 	      /* Be sure there is enough room for the expansion.  */
   1082 	      len = (vec->rec_len + 1) & ~1;
   1083 	      if (len > vec->dcx_max)
   1084 		{
   1085 		  while (len > vec->dcx_max)
   1086 		    vec->dcx_max *= 2;
   1087 		  vec->dcx_buf = bfd_alloc (abfd, vec->dcx_max);
   1088 		  if (vec->dcx_buf == NULL)
   1089 		    return -1;
   1090 		}
   1091 
   1092 	      /* Read the compressed record.  */
   1093 	      vec->dcx_rlen = len;
   1094 	      if (vec->rec_len == 3)
   1095 		{
   1096 		  /* Already read.  */
   1097 		  memcpy (vec->dcx_buf, vec->pattern, 3);
   1098 		}
   1099 	      else
   1100 		{
   1101 		  elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len);
   1102 		  if (elen != len)
   1103 		    return -1;
   1104 		}
   1105 
   1106 	      /* Dummy expansion to get the expanded length.  */
   1107 	      vec->dcx_offset = 0;
   1108 	      vec->dcx_sbm = vec->dcxsbms;
   1109 	      vec->dcx_pos = 0;
   1110 	      elen = vms_lib_dcx (vec, NULL, 0x10000);
   1111 	      if (elen < 0)
   1112 		return -1;
   1113 	      vec->rec_len = elen;
   1114 	      vec->rec_rem = elen;
   1115 
   1116 	      /* Reset the state.  */
   1117 	      vec->dcx_offset = 0;
   1118 	      vec->dcx_sbm = vec->dcxsbms;
   1119 	      vec->dcx_pos = 0;
   1120 	    }
   1121 	}
   1122       if (vec->rec_pos < 0)
   1123 	{
   1124 	  unsigned char c;
   1125 	  switch (vec->rec_pos)
   1126 	    {
   1127 	    case REC_POS_LEN0:
   1128 	      c = vec->rec_len & 0xff;
   1129 	      vec->rec_pos = REC_POS_LEN1;
   1130 	      break;
   1131 	    case REC_POS_LEN1:
   1132 	      c = (vec->rec_len >> 8) & 0xff;
   1133 	      vec->rec_pos = 0;
   1134 	      break;
   1135 	    case REC_POS_PAD:
   1136 	      c = 0;
   1137 	      vec->rec_rem = 0;
   1138 	      break;
   1139 	    case REC_POS_NL:
   1140 	      c = '\n';
   1141 	      vec->rec_rem = 0;
   1142 	      break;
   1143 	    default:
   1144 	      abort ();
   1145 	    }
   1146 	  if (buf != NULL)
   1147 	    {
   1148 	      *buf = c;
   1149 	      buf++;
   1150 	    }
   1151 	  nbytes--;
   1152 	  res++;
   1153 	  continue;
   1154 	}
   1155 
   1156       if (nbytes > vec->rec_rem)
   1157 	chunk = vec->rec_rem;
   1158       else
   1159 	chunk = nbytes;
   1160 
   1161       if (vec->dcxsbms != NULL)
   1162 	{
   1163 	  /* Optimize the stat() case: no need to decompress again as we
   1164 	     know the length.  */
   1165 	  if (!(buf == NULL && chunk == vec->rec_rem))
   1166 	    chunk = vms_lib_dcx (vec, buf, chunk);
   1167 	}
   1168       else
   1169 	{
   1170 	  if (vec->rec_len == 3)
   1171 	    {
   1172 	      if (buf != NULL)
   1173 		memcpy (buf, vec->pattern + vec->rec_pos, chunk);
   1174 	    }
   1175 	  else
   1176 	    chunk = vms_lib_bread_raw (abfd, buf, chunk);
   1177 	}
   1178       if (chunk < 0)
   1179 	return -1;
   1180       res += chunk;
   1181       if (buf != NULL)
   1182 	buf += chunk;
   1183       nbytes -= chunk;
   1184       vec->rec_pos += chunk;
   1185       vec->rec_rem -= chunk;
   1186 
   1187       if (vec->rec_rem == 0)
   1188 	{
   1189 	  /* End of record reached.  */
   1190 	  if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
   1191 	    {
   1192 	      if ((vec->rec_len & 1) == 1
   1193 		  && vec->rec_len != 3
   1194 		  && vec->dcxsbms == NULL)
   1195 		{
   1196 		  /* Eat the pad byte.  */
   1197 		  unsigned char pad;
   1198 		  if (vms_lib_bread_raw (abfd, &pad, 1) != 1)
   1199 		    return -1;
   1200 		}
   1201 	      vec->rec_pos = REC_POS_NL;
   1202 	      vec->rec_rem = 1;
   1203 	    }
   1204 	  else
   1205 	    {
   1206 	      if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL)
   1207 		{
   1208 		  vec->rec_pos = REC_POS_PAD;
   1209 		  vec->rec_rem = 1;
   1210 		}
   1211 	    }
   1212 	}
   1213     }
   1214   vec->where += res;
   1215   return res;
   1216 }
   1217 
   1218 /* Standard function, but we currently only handle the rewind case.  */
   1219 
   1220 static int
   1221 vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence)
   1222 {
   1223   struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
   1224 
   1225   if (whence == SEEK_SET && offset == 0)
   1226     {
   1227       vec->where = 0;
   1228       vec->rec_rem = 0;
   1229       vec->dcx_pos = -1;
   1230       vec->blk_off = vec->init_blk_off;
   1231       vec->next_block = vec->init_next_block;
   1232 
   1233       if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0)
   1234 	return -1;
   1235     }
   1236   else
   1237     abort ();
   1238   return 0;
   1239 }
   1240 
   1241 static file_ptr
   1242 vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED,
   1243 	      const void *where ATTRIBUTE_UNUSED,
   1244 	      file_ptr nbytes ATTRIBUTE_UNUSED)
   1245 {
   1246   return -1;
   1247 }
   1248 
   1249 static int
   1250 vms_lib_bclose (struct bfd *abfd)
   1251 {
   1252   abfd->iostream = NULL;
   1253   return 0;
   1254 }
   1255 
   1256 static int
   1257 vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
   1258 {
   1259   return 0;
   1260 }
   1261 
   1262 static int
   1263 vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
   1264 	       struct stat *sb ATTRIBUTE_UNUSED)
   1265 {
   1266   /* Not supported.  */
   1267   return 0;
   1268 }
   1269 
   1270 static void *
   1271 vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
   1272 	       void *addr ATTRIBUTE_UNUSED,
   1273 	       size_t len ATTRIBUTE_UNUSED,
   1274 	       int prot ATTRIBUTE_UNUSED,
   1275 	       int flags ATTRIBUTE_UNUSED,
   1276 	       file_ptr offset ATTRIBUTE_UNUSED,
   1277 	       void **map_addr ATTRIBUTE_UNUSED,
   1278 	       size_t *map_len ATTRIBUTE_UNUSED)
   1279 {
   1280   return MAP_FAILED;
   1281 }
   1282 
   1283 static const struct bfd_iovec vms_lib_iovec = {
   1284   &vms_lib_bread, &vms_lib_bwrite, &vms_lib_btell, &vms_lib_bseek,
   1285   &vms_lib_bclose, &vms_lib_bflush, &vms_lib_bstat, &vms_lib_bmmap
   1286 };
   1287 
   1288 /* Open a library module.  FILEPOS is the position of the module header.  */
   1289 
   1290 static bool
   1291 vms_lib_bopen (bfd *el, file_ptr filepos)
   1292 {
   1293   struct vms_lib_iovec *vec;
   1294   unsigned char buf[256];
   1295   struct vms_mhd *mhd;
   1296   struct lib_tdata *tdata = bfd_libdata (el->my_archive);
   1297   unsigned int len;
   1298 
   1299   /* Allocate and initialized the iovec.  */
   1300   vec = bfd_zalloc (el, sizeof (*vec));
   1301   if (vec == NULL)
   1302     return false;
   1303 
   1304   el->iostream = vec;
   1305   el->iovec = &vms_lib_iovec;
   1306 
   1307   /* File length is not known.  */
   1308   vec->file_len = -1;
   1309 
   1310   /* Read the first data block.  */
   1311   vec->next_block = filepos & ~(VMS_BLOCK_SIZE - 1);
   1312   vec->blk_off = DATA__LENGTH;
   1313   if (!vms_lib_read_block (el))
   1314     return false;
   1315 
   1316   /* Prepare to read the first record.  */
   1317   vec->blk_off = filepos & (VMS_BLOCK_SIZE - 1);
   1318   vec->rec_rem = 0;
   1319   if (bfd_seek (el->my_archive, filepos, SEEK_SET) != 0)
   1320     return false;
   1321 
   1322   /* Read Record length + MHD + align byte.  */
   1323   len = tdata->mhd_size;
   1324   if (vms_lib_bread_raw (el, buf, 2) != 2)
   1325     return false;
   1326   if (bfd_getl16 (buf) != len)
   1327     return false;
   1328   len = (len + 1) & ~1;
   1329   BFD_ASSERT (len <= sizeof (buf));
   1330   if (vms_lib_bread_raw (el, buf, len) != len)
   1331     return false;
   1332 
   1333   /* Get info from mhd.  */
   1334   mhd = (struct vms_mhd *)buf;
   1335   /* Check id.  */
   1336   if (mhd->id != MHD__C_MHDID)
   1337     return false;
   1338   if (len >= MHD__C_MHDLEN + 1)
   1339     el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
   1340   el->mtime = vms_rawtime_to_time_t (mhd->datim);
   1341   el->mtime_set = true;
   1342 
   1343   /* Reinit the iovec so that seek() will point to the first record after
   1344      the mhd.  */
   1345   vec->where = 0;
   1346   vec->init_blk_off = vec->blk_off;
   1347   vec->init_next_block = vec->next_block;
   1348   vec->first_block = bfd_tell (el->my_archive);
   1349   vec->dcxsbms = bfd_libdata (el->my_archive)->dcxsbm;
   1350 
   1351   if (vec->dcxsbms != NULL)
   1352     {
   1353       /* Handle DCX.  */
   1354       vec->dcx_max = 10 * 1024;
   1355       vec->dcx_buf = bfd_alloc (el, vec->dcx_max);
   1356       vec->dcx_pos = -1;
   1357       if (vec->dcx_buf == NULL)
   1358 	return -1;
   1359     }
   1360   return true;
   1361 }
   1362 
   1363 /* Get member MODIDX.  Return NULL in case of error.  */
   1364 
   1365 static bfd *
   1366 _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
   1367 {
   1368   struct lib_tdata *tdata = bfd_libdata (abfd);
   1369   bfd *res;
   1370   file_ptr file_off;
   1371   const char *name;
   1372   char *newname;
   1373   size_t namelen;
   1374 
   1375   /* Sanity check.  */
   1376   if (modidx >= tdata->nbr_modules)
   1377     return NULL;
   1378 
   1379   /* Already loaded.  */
   1380   if (tdata->cache[modidx])
   1381     return tdata->cache[modidx];
   1382 
   1383   /* Build it.  */
   1384   file_off = tdata->modules[modidx].file_offset;
   1385   if (tdata->type != LBR__C_TYP_IOBJ)
   1386     {
   1387       res = _bfd_create_empty_archive_element_shell (abfd);
   1388       if (res == NULL)
   1389 	return NULL;
   1390 
   1391       /* Special reader to deal with data blocks.  */
   1392       if (!vms_lib_bopen (res, file_off))
   1393 	return NULL;
   1394     }
   1395   else
   1396     {
   1397       char buf[256];
   1398       struct vms_mhd *mhd;
   1399       struct areltdata *arelt;
   1400 
   1401       /* Sanity check.  The MHD must be big enough to contain module size.  */
   1402       if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4)
   1403 	return NULL;
   1404 
   1405       /* Read the MHD now.  */
   1406       if (bfd_seek (abfd, file_off, SEEK_SET) != 0)
   1407 	return NULL;
   1408       if (bfd_read (buf, tdata->mhd_size, abfd) != tdata->mhd_size)
   1409 	return NULL;
   1410 
   1411       mhd = (struct vms_mhd *) buf;
   1412       if (mhd->id != MHD__C_MHDID)
   1413 	return NULL;
   1414 
   1415       res = _bfd_create_empty_archive_element_shell (abfd);
   1416       if (res == NULL)
   1417 	return NULL;
   1418       arelt = bfd_zmalloc (sizeof (*arelt));
   1419       if (arelt == NULL)
   1420 	{
   1421 	  bfd_close (res);
   1422 	  return NULL;
   1423 	}
   1424       res->arelt_data = arelt;
   1425 
   1426       /* Get info from mhd.  */
   1427       if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1)
   1428 	res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
   1429       res->mtime = vms_rawtime_to_time_t (mhd->datim);
   1430       res->mtime_set = true;
   1431 
   1432       arelt->parsed_size = bfd_getl32 (mhd->modsize);
   1433 
   1434       /* No need for a special reader as members are stored linearly.
   1435 	 Just skip the MHD.  */
   1436       res->origin = file_off + tdata->mhd_size;
   1437     }
   1438 
   1439   /* Set filename.  */
   1440   name = tdata->modules[modidx].name;
   1441   namelen = strlen (name);
   1442   newname = bfd_malloc (namelen + 4 + 1);
   1443   if (newname == NULL)
   1444     {
   1445       bfd_close (res);
   1446       return NULL;
   1447     }
   1448   strcpy (newname, name);
   1449   switch (tdata->type)
   1450     {
   1451     case LBR__C_TYP_IOBJ:
   1452     case LBR__C_TYP_EOBJ:
   1453       /* For object archives, append .obj to mimic standard behaviour.  */
   1454       strcpy (newname + namelen, ".obj");
   1455       break;
   1456     default:
   1457       break;
   1458     }
   1459   bfd_set_filename (res, newname);
   1460   free (newname);
   1461   if (bfd_get_filename (res) == NULL)
   1462     {
   1463       bfd_close (res);
   1464       return NULL;
   1465     }
   1466 
   1467   tdata->cache[modidx] = res;
   1468 
   1469   return res;
   1470 }
   1471 
   1472 /* Standard function: get member at IDX.  */
   1473 
   1474 bfd *
   1475 _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
   1476 {
   1477   struct lib_tdata *tdata = bfd_libdata (abfd);
   1478   file_ptr file_off;
   1479   unsigned int modidx;
   1480 
   1481   /* Check symidx.  */
   1482   if (symidx > tdata->artdata.symdef_count)
   1483     return NULL;
   1484   file_off = tdata->artdata.symdefs[symidx].file_offset;
   1485 
   1486   /* Linear-scan.  */
   1487   for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
   1488     {
   1489       if (tdata->modules[modidx].file_offset == file_off)
   1490 	break;
   1491     }
   1492   if (modidx >= tdata->nbr_modules)
   1493     return NULL;
   1494 
   1495   return _bfd_vms_lib_get_module (abfd, modidx);
   1496 }
   1497 
   1498 /* Elements of an imagelib are stubs.  You can get the real image with this
   1499    function.  */
   1500 
   1501 bfd *
   1502 _bfd_vms_lib_get_imagelib_file (bfd *el)
   1503 {
   1504   bfd *archive = el->my_archive;
   1505   const char *modname = bfd_get_filename (el);
   1506   int modlen = strlen (modname);
   1507   char *filename;
   1508   int j;
   1509   bfd *res;
   1510 
   1511   /* Convert module name to lower case and append '.exe'.  */
   1512   filename = bfd_alloc (el, modlen + 5);
   1513   if (filename == NULL)
   1514     return NULL;
   1515   for (j = 0; j < modlen; j++)
   1516     if (ISALPHA (modname[j]))
   1517       filename[j] = TOLOWER (modname[j]);
   1518     else
   1519       filename[j] = modname[j];
   1520   memcpy (filename + modlen, ".exe", 5);
   1521 
   1522   filename = _bfd_append_relative_path (archive, filename);
   1523   if (filename == NULL)
   1524     return NULL;
   1525   res = bfd_openr (filename, NULL);
   1526 
   1527   if (res == NULL)
   1528     {
   1529       /* xgettext:c-format */
   1530       _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
   1531 			 filename, bfd_get_filename (archive));
   1532       bfd_release (archive, filename);
   1533       return NULL;
   1534     }
   1535 
   1536   /* FIXME: put it in a cache ?  */
   1537   return res;
   1538 }
   1539 
   1540 /* Standard function.  */
   1541 
   1542 bfd *
   1543 _bfd_vms_lib_openr_next_archived_file (bfd *archive,
   1544 				       bfd *last_file)
   1545 {
   1546   unsigned int idx;
   1547   bfd *res;
   1548 
   1549   if (!last_file)
   1550     idx = 0;
   1551   else
   1552     idx = last_file->proxy_origin + 1;
   1553 
   1554   if (idx >= bfd_libdata (archive)->nbr_modules)
   1555     {
   1556       bfd_set_error (bfd_error_no_more_archived_files);
   1557       return NULL;
   1558     }
   1559 
   1560   res = _bfd_vms_lib_get_module (archive, idx);
   1561   if (res == NULL)
   1562     return res;
   1563   res->proxy_origin = idx;
   1564   return res;
   1565 }
   1566 
   1567 /* Standard function.  Just compute the length.  */
   1568 
   1569 int
   1570 _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
   1571 {
   1572   struct lib_tdata *tdata;
   1573 
   1574   /* Sanity check.  */
   1575   if (abfd->my_archive == NULL)
   1576     {
   1577       bfd_set_error (bfd_error_invalid_operation);
   1578       return -1;
   1579     }
   1580 
   1581   tdata = bfd_libdata (abfd->my_archive);
   1582   if (tdata->type != LBR__C_TYP_IOBJ)
   1583     {
   1584       struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
   1585 
   1586       if (vec->file_len == (ufile_ptr)-1)
   1587 	{
   1588 	  if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
   1589 	    return -1;
   1590 
   1591 	  /* Compute length.  */
   1592 	  while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
   1593 	    ;
   1594 	}
   1595       st->st_size = vec->file_len;
   1596     }
   1597   else
   1598     {
   1599       st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
   1600     }
   1601 
   1602   if (abfd->mtime_set)
   1603     st->st_mtime = abfd->mtime;
   1604   else
   1605     st->st_mtime = 0;
   1606   st->st_uid = 0;
   1607   st->st_gid = 0;
   1608   st->st_mode = 0644;
   1609 
   1610   return 0;
   1611 }
   1612 
   1613 /* Internal representation of an index entry.  */
   1614 
   1615 struct lib_index
   1616 {
   1617   /* Corresponding archive member.  */
   1618   bfd *abfd;
   1619 
   1620   /* Number of reference to this entry.  */
   1621   unsigned int ref;
   1622 
   1623   /* Length of the key.  */
   1624   unsigned short namlen;
   1625 
   1626   /* Key.  */
   1627   const char *name;
   1628 };
   1629 
   1630 /* Used to sort index entries.  */
   1631 
   1632 static int
   1633 lib_index_cmp (const void *lv, const void *rv)
   1634 {
   1635   const struct lib_index *l = lv;
   1636   const struct lib_index *r = rv;
   1637 
   1638   return strcmp (l->name, r->name);
   1639 }
   1640 
   1641 /* Maximum number of index blocks level.  */
   1642 
   1643 #define MAX_LEVEL 10
   1644 
   1645 /* Get the size of an index entry.  */
   1646 
   1647 static unsigned int
   1648 get_idxlen (struct lib_index *idx, bool is_elfidx)
   1649 {
   1650   if (is_elfidx)
   1651     {
   1652       /* 9 is the size of struct vms_elfidx without keyname.  */
   1653       if (idx->namlen > MAX_KEYLEN)
   1654 	return 9 + sizeof (struct vms_kbn);
   1655       else
   1656 	return 9 + idx->namlen;
   1657     }
   1658   else
   1659     {
   1660       /* 7 is the size of struct vms_idx without keyname.  */
   1661       return 7 + idx->namlen;
   1662     }
   1663 }
   1664 
   1665 /* Write the index composed by NBR symbols contained in IDX.
   1666    VBN is the first vbn to be used, and will contain on return the last vbn.
   1667    Can be called with ABFD set to NULL just to size the index.
   1668    If not null, TOPVBN will be assigned to the vbn of the root index tree.
   1669    IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
   1670    Return TRUE on success.  */
   1671 
   1672 static bool
   1673 vms_write_index (bfd *abfd,
   1674 		 struct lib_index *idx, unsigned int nbr, unsigned int *vbn,
   1675 		 unsigned int *topvbn, bool is_elfidx)
   1676 {
   1677   /* The index is organized as a tree.  This function implements a naive
   1678      algorithm to balance the tree: it fills the leaves, and create a new
   1679      branch when all upper leaves and branches are full.  We only keep in
   1680      memory a path to the current leaf.  */
   1681   unsigned int i;
   1682   int j;
   1683   int level;
   1684   /* Disk blocks for the current path.  */
   1685   struct vms_indexdef *rblk[MAX_LEVEL];
   1686   /* Info on the current blocks.  */
   1687   struct idxblk
   1688   {
   1689     unsigned int vbn;		/* VBN of the block.  */
   1690     /* The last entry is identified so that it could be copied to the
   1691        parent block.  */
   1692     unsigned short len;		/* Length up to the last entry.  */
   1693     unsigned short lastlen;	/* Length of the last entry.  */
   1694   } blk[MAX_LEVEL];
   1695 
   1696   /* The kbn blocks are used to store long symbol names.  */
   1697   unsigned int kbn_sz = 0;   /* Number of bytes available in the kbn block.  */
   1698   unsigned int kbn_vbn = 0;  /* VBN of the kbn block.  */
   1699   unsigned char *kbn_blk = NULL; /* Contents of the kbn block.  */
   1700 
   1701   if (nbr == 0)
   1702     {
   1703       /* No entries.  Very easy to handle.  */
   1704       if (topvbn != NULL)
   1705 	*topvbn = 0;
   1706       return true;
   1707     }
   1708 
   1709   if (abfd == NULL)
   1710     {
   1711       /* Sort the index the first time this function is called.  */
   1712       qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp);
   1713     }
   1714 
   1715   /* Allocate first index block.  */
   1716   level = 1;
   1717   if (abfd != NULL)
   1718     rblk[0] = bfd_zmalloc (sizeof (struct vms_indexdef));
   1719   blk[0].vbn = (*vbn)++;
   1720   blk[0].len = 0;
   1721   blk[0].lastlen = 0;
   1722 
   1723   for (i = 0; i < nbr; i++, idx++)
   1724     {
   1725       unsigned int idxlen;
   1726       int flush = 0;
   1727       unsigned int key_vbn = 0;
   1728       unsigned int key_off = 0;
   1729 
   1730       idxlen = get_idxlen (idx, is_elfidx);
   1731 
   1732       if (is_elfidx && idx->namlen > MAX_KEYLEN)
   1733 	{
   1734 	  /* If the key (ie name) is too long, write it in the kbn block.  */
   1735 	  unsigned int kl = idx->namlen;
   1736 	  unsigned int kl_chunk;
   1737 	  const char *key = idx->name;
   1738 
   1739 	  /* Write the key in the kbn, chunk after chunk.  */
   1740 	  do
   1741 	    {
   1742 	      if (kbn_sz < sizeof (struct vms_kbn))
   1743 		{
   1744 		  /* Not enough room in the kbn block.  */
   1745 		  if (abfd != NULL)
   1746 		    {
   1747 		      /* Write it to the disk (if there is one).  */
   1748 		      if (kbn_vbn != 0)
   1749 			{
   1750 			  if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
   1751 			    goto err;
   1752 			}
   1753 		      else
   1754 			{
   1755 			  kbn_blk = bfd_malloc (VMS_BLOCK_SIZE);
   1756 			  if (kbn_blk == NULL)
   1757 			    goto err;
   1758 			}
   1759 		      *(unsigned short *)kbn_blk = 0;
   1760 		    }
   1761 		  /* Allocate a new block for the keys.  */
   1762 		  kbn_vbn = (*vbn)++;
   1763 		  kbn_sz = VMS_BLOCK_SIZE - 2;
   1764 		}
   1765 	      /* Size of the chunk written to the current key block.  */
   1766 	      if (kl + sizeof (struct vms_kbn) > kbn_sz)
   1767 		kl_chunk = kbn_sz - sizeof (struct vms_kbn);
   1768 	      else
   1769 		kl_chunk = kl;
   1770 
   1771 	      if (kbn_blk != NULL)
   1772 		{
   1773 		  struct vms_kbn *kbn;
   1774 
   1775 		  kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz);
   1776 
   1777 		  if (key_vbn == 0)
   1778 		    {
   1779 		      /* Save the rfa of the first chunk.  */
   1780 		      key_vbn = kbn_vbn;
   1781 		      key_off = VMS_BLOCK_SIZE - kbn_sz;
   1782 		    }
   1783 
   1784 		  bfd_putl16 (kl_chunk, kbn->keylen);
   1785 		  if (kl_chunk == kl)
   1786 		    {
   1787 		      /* No next chunk.  */
   1788 		      bfd_putl32 (0, kbn->rfa.vbn);
   1789 		      bfd_putl16 (0, kbn->rfa.offset);
   1790 		    }
   1791 		  else
   1792 		    {
   1793 		      /* Next chunk will be at the start of the next block.  */
   1794 		      bfd_putl32 (*vbn, kbn->rfa.vbn);
   1795 		      bfd_putl16 (2, kbn->rfa.offset);
   1796 		    }
   1797 		  memcpy ((char *)(kbn + 1), key, kl_chunk);
   1798 		  key += kl_chunk;
   1799 		}
   1800 	      kl -= kl_chunk;
   1801 	      kl_chunk = (kl_chunk + 1) & ~1;	  /* Always align.  */
   1802 	      kbn_sz -= kl_chunk + sizeof (struct vms_kbn);
   1803 	    }
   1804 	  while (kl > 0);
   1805 	}
   1806 
   1807       /* Check if a block might overflow.  In this case we will flush this
   1808 	 block and all the blocks below it.  */
   1809       for (j = 0; j < level; j++)
   1810 	if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ)
   1811 	  flush = j + 1;
   1812 
   1813       for (j = 0; j < level; j++)
   1814 	{
   1815 	  if (j < flush)
   1816 	    {
   1817 	      /* There is not enough room to write the new entry in this
   1818 		 block or in a parent block.  */
   1819 
   1820 	      if (j + 1 == level)
   1821 		{
   1822 		  BFD_ASSERT (level < MAX_LEVEL);
   1823 
   1824 		  /* Need to create a parent.  */
   1825 		  if (abfd != NULL)
   1826 		    {
   1827 		      rblk[level] = bfd_zmalloc (sizeof (struct vms_indexdef));
   1828 		      bfd_putl32 (*vbn, rblk[j]->parent);
   1829 		    }
   1830 		  blk[level].vbn = (*vbn)++;
   1831 		  blk[level].len = 0;
   1832 		  blk[level].lastlen = blk[j].lastlen;
   1833 
   1834 		  level++;
   1835 		}
   1836 
   1837 	      /* Update parent block: write the last entry from the current
   1838 		 block.  */
   1839 	      if (abfd != NULL)
   1840 		{
   1841 		  struct vms_rfa *rfa;
   1842 
   1843 		  /* Pointer to the last entry in parent block.  */
   1844 		  rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len);
   1845 
   1846 		  /* Copy the whole entry.  */
   1847 		  BFD_ASSERT (blk[j + 1].lastlen == blk[j].lastlen);
   1848 		  memcpy (rfa, rblk[j]->keys + blk[j].len, blk[j].lastlen);
   1849 		  /* Fix the entry (which in always the first field of an
   1850 		     entry.  */
   1851 		  bfd_putl32 (blk[j].vbn, rfa->vbn);
   1852 		  bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
   1853 		}
   1854 
   1855 	      if (j + 1 == flush)
   1856 		{
   1857 		  /* And allocate it.  Do it only on the block that won't be
   1858 		     flushed (so that the parent of the parent can be
   1859 		     updated too).  */
   1860 		  blk[j + 1].len += blk[j + 1].lastlen;
   1861 		  blk[j + 1].lastlen = 0;
   1862 		}
   1863 
   1864 	      /* Write this block on the disk.  */
   1865 	      if (abfd != NULL)
   1866 		{
   1867 		  bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
   1868 		  if (!vms_write_block (abfd, blk[j].vbn, rblk[j]))
   1869 		    goto err;
   1870 		}
   1871 
   1872 	      /* Reset this block.  */
   1873 	      blk[j].len = 0;
   1874 	      blk[j].lastlen = 0;
   1875 	      blk[j].vbn = (*vbn)++;
   1876 	    }
   1877 
   1878 	  /* Append it to the block.  */
   1879 	  if (j == 0)
   1880 	    {
   1881 	      /* Keep the previous last entry.  */
   1882 	      blk[j].len += blk[j].lastlen;
   1883 
   1884 	      if (abfd != NULL)
   1885 		{
   1886 		  struct vms_rfa *rfa;
   1887 
   1888 		  rfa = (struct vms_rfa *)(rblk[j]->keys + blk[j].len);
   1889 		  bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
   1890 			      rfa->vbn);
   1891 		  bfd_putl16
   1892 		    ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE)
   1893 		     + (is_elfidx ? 0 : DATA__DATA),
   1894 		     rfa->offset);
   1895 
   1896 		  if (is_elfidx)
   1897 		    {
   1898 		      /* Use elfidx format.  */
   1899 		      struct vms_elfidx *en = (struct vms_elfidx *)rfa;
   1900 
   1901 		      en->flags = 0;
   1902 		      if (key_vbn != 0)
   1903 			{
   1904 			  /* Long symbol name.  */
   1905 			  struct vms_kbn *k = (struct vms_kbn *)(en->keyname);
   1906 			  bfd_putl16 (sizeof (struct vms_kbn), en->keylen);
   1907 			  bfd_putl16 (idx->namlen, k->keylen);
   1908 			  bfd_putl32 (key_vbn, k->rfa.vbn);
   1909 			  bfd_putl16 (key_off, k->rfa.offset);
   1910 			  en->flags |= ELFIDX__SYMESC;
   1911 			}
   1912 		      else
   1913 			{
   1914 			  bfd_putl16 (idx->namlen, en->keylen);
   1915 			  memcpy (en->keyname, idx->name, idx->namlen);
   1916 			}
   1917 		    }
   1918 		  else
   1919 		    {
   1920 		      /* Use idx format.  */
   1921 		      struct vms_idx *en = (struct vms_idx *)rfa;
   1922 		      en->keylen = idx->namlen;
   1923 		      memcpy (en->keyname, idx->name, idx->namlen);
   1924 		    }
   1925 		}
   1926 	    }
   1927 	  /* The last added key can now be the last one all blocks in the
   1928 	     path.  */
   1929 	  blk[j].lastlen = idxlen;
   1930 	}
   1931     }
   1932 
   1933   /* Save VBN of the root.  */
   1934   if (topvbn != NULL)
   1935     *topvbn = blk[level - 1].vbn;
   1936 
   1937   if (abfd == NULL)
   1938     return true;
   1939 
   1940   /* Flush.  */
   1941   for (j = 1; j < level; j++)
   1942     {
   1943       /* Update parent block: write the new entry.  */
   1944       unsigned char *en;
   1945       unsigned char *par;
   1946       struct vms_rfa *rfa;
   1947 
   1948       en = rblk[j - 1]->keys + blk[j - 1].len;
   1949       par = rblk[j]->keys + blk[j].len;
   1950       BFD_ASSERT (blk[j].lastlen == blk[j - 1].lastlen);
   1951       memcpy (par, en, blk[j - 1].lastlen);
   1952       rfa = (struct vms_rfa *)par;
   1953       bfd_putl32 (blk[j - 1].vbn, rfa->vbn);
   1954       bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
   1955     }
   1956 
   1957   for (j = 0; j < level; j++)
   1958     {
   1959       /* Write this block on the disk.  */
   1960       bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
   1961       if (!vms_write_block (abfd, blk[j].vbn, rblk[j]))
   1962 	goto err;
   1963 
   1964       free (rblk[j]);
   1965       rblk[j] = NULL;
   1966     }
   1967 
   1968   /* Write the last kbn (if any).  */
   1969   if (kbn_vbn != 0)
   1970     {
   1971       if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
   1972 	goto err;
   1973       free (kbn_blk);
   1974     }
   1975 
   1976   return true;
   1977 
   1978  err:
   1979   if (abfd != NULL)
   1980     {
   1981       for (j = 0; j < level; j++)
   1982 	free (rblk[j]);
   1983       free (kbn_blk);
   1984     }
   1985   return false;
   1986 }
   1987 
   1988 /* Append data to the data block DATA.  Force write if PAD is true.  */
   1989 
   1990 static bool
   1991 vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off,
   1992 		      const unsigned char *buf, unsigned int len, int pad)
   1993 {
   1994   while (len > 0 || pad)
   1995     {
   1996       unsigned int doff = *off & (VMS_BLOCK_SIZE - 1);
   1997       unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff;
   1998       unsigned int l;
   1999 
   2000       l = (len > remlen) ? remlen : len;
   2001       memcpy (data->data + doff, buf, l);
   2002       buf += l;
   2003       len -= l;
   2004       doff += l;
   2005       *off += l;
   2006 
   2007       if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad))
   2008 	{
   2009 	  data->recs = 0;
   2010 	  data->fill_1 = 0;
   2011 	  bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link);
   2012 
   2013 	  if (bfd_write (data, sizeof (*data), arch) != sizeof (*data))
   2014 	    return false;
   2015 
   2016 	  *off += DATA__LENGTH - doff;
   2017 
   2018 	  if (len == 0)
   2019 	    break;
   2020 	}
   2021     }
   2022   return true;
   2023 }
   2024 
   2025 /* Build the symbols index.  */
   2026 
   2027 static bool
   2028 _bfd_vms_lib_build_map (unsigned int nbr_modules,
   2029 			struct lib_index *modules,
   2030 			unsigned int *res_cnt,
   2031 			struct lib_index **res)
   2032 {
   2033   unsigned int i;
   2034   asymbol **syms = NULL;
   2035   long syms_max = 0;
   2036   struct lib_index *map = NULL;
   2037   unsigned int map_max = 1024;		/* Fine initial default.  */
   2038   unsigned int map_count = 0;
   2039 
   2040   map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index));
   2041   if (map == NULL)
   2042     goto error_return;
   2043 
   2044   /* Gather symbols.  */
   2045   for (i = 0; i < nbr_modules; i++)
   2046     {
   2047       long storage;
   2048       long symcount;
   2049       long src_count;
   2050       bfd *current = modules[i].abfd;
   2051 
   2052       if ((bfd_get_file_flags (current) & HAS_SYMS) == 0)
   2053 	continue;
   2054 
   2055       storage = bfd_get_symtab_upper_bound (current);
   2056       if (storage < 0)
   2057 	goto error_return;
   2058 
   2059       if (storage != 0)
   2060 	{
   2061 	  if (storage > syms_max)
   2062 	    {
   2063 	      free (syms);
   2064 	      syms_max = storage;
   2065 	      syms = (asymbol **) bfd_malloc (syms_max);
   2066 	      if (syms == NULL)
   2067 		goto error_return;
   2068 	    }
   2069 	  symcount = bfd_canonicalize_symtab (current, syms);
   2070 	  if (symcount < 0)
   2071 	    goto error_return;
   2072 
   2073 	  /* Now map over all the symbols, picking out the ones we
   2074 	     want.  */
   2075 	  for (src_count = 0; src_count < symcount; src_count++)
   2076 	    {
   2077 	      flagword flags = (syms[src_count])->flags;
   2078 	      asection *sec = syms[src_count]->section;
   2079 
   2080 	      if ((flags & BSF_GLOBAL
   2081 		   || flags & BSF_WEAK
   2082 		   || flags & BSF_INDIRECT
   2083 		   || bfd_is_com_section (sec))
   2084 		  && ! bfd_is_und_section (sec))
   2085 		{
   2086 		  struct lib_index *new_map;
   2087 
   2088 		  /* This symbol will go into the archive header.  */
   2089 		  if (map_count == map_max)
   2090 		    {
   2091 		      map_max *= 2;
   2092 		      new_map = (struct lib_index *)
   2093 			bfd_realloc (map, map_max * sizeof (struct lib_index));
   2094 		      if (new_map == NULL)
   2095 			goto error_return;
   2096 		      map = new_map;
   2097 		    }
   2098 
   2099 		  map[map_count].abfd = current;
   2100 		  map[map_count].namlen = strlen (syms[src_count]->name);
   2101 		  map[map_count].name = syms[src_count]->name;
   2102 		  map_count++;
   2103 		  modules[i].ref++;
   2104 		}
   2105 	    }
   2106 	}
   2107     }
   2108 
   2109   *res_cnt = map_count;
   2110   *res = map;
   2111   free (syms);
   2112   return true;
   2113 
   2114  error_return:
   2115   free (syms);
   2116   free (map);
   2117   return false;
   2118 }
   2119 
   2120 /* Do the hard work: write an archive on the disk.  */
   2121 
   2122 bool
   2123 _bfd_vms_lib_write_archive_contents (bfd *arch)
   2124 {
   2125   bfd *current;
   2126   unsigned int nbr_modules;
   2127   struct lib_index *modules;
   2128   unsigned int nbr_symbols;
   2129   struct lib_index *symbols = NULL;
   2130   struct lib_tdata *tdata = bfd_libdata (arch);
   2131   unsigned int i;
   2132   file_ptr off;
   2133   unsigned int nbr_mod_iblk;
   2134   unsigned int nbr_sym_iblk;
   2135   unsigned int vbn;
   2136   unsigned int mod_idx_vbn;
   2137   unsigned int sym_idx_vbn;
   2138   bool is_elfidx = tdata->kind == vms_lib_ia64;
   2139   unsigned int max_keylen = is_elfidx ? MAX_EKEYLEN : MAX_KEYLEN;
   2140 
   2141   /* Count the number of modules (and do a first sanity check).  */
   2142   nbr_modules = 0;
   2143   for (current = arch->archive_head;
   2144        current != NULL;
   2145        current = current->archive_next)
   2146     {
   2147       /* This check is checking the bfds for the objects we're reading
   2148 	 from (which are usually either an object file or archive on
   2149 	 disk), not the archive entries we're writing to.  We don't
   2150 	 actually create bfds for the archive members, we just copy
   2151 	 them byte-wise when we write out the archive.  */
   2152       if (bfd_write_p (current) || !bfd_check_format (current, bfd_object))
   2153 	{
   2154 	  bfd_set_error (bfd_error_invalid_operation);
   2155 	  goto input_err;
   2156 	}
   2157 
   2158       nbr_modules++;
   2159     }
   2160 
   2161   /* Build the modules list.  */
   2162   BFD_ASSERT (tdata->modules == NULL);
   2163   modules = bfd_alloc (arch, nbr_modules * sizeof (struct lib_index));
   2164   if (modules == NULL)
   2165     return false;
   2166 
   2167   for (current = arch->archive_head, i = 0;
   2168        current != NULL;
   2169        current = current->archive_next, i++)
   2170     {
   2171       unsigned int nl;
   2172 
   2173       modules[i].abfd = current;
   2174       modules[i].name = vms_get_module_name (bfd_get_filename (current), false);
   2175       modules[i].ref = 1;
   2176 
   2177       /* FIXME: silently truncate long names ?  */
   2178       nl = strlen (modules[i].name);
   2179       modules[i].namlen = (nl > max_keylen ? max_keylen : nl);
   2180     }
   2181 
   2182   /* Create the module index.  */
   2183   vbn = 0;
   2184   if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL, is_elfidx))
   2185     return false;
   2186   nbr_mod_iblk = vbn;
   2187 
   2188   /* Create symbol index.  */
   2189   if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols))
   2190     goto err;
   2191 
   2192   vbn = 0;
   2193   if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx))
   2194     goto err;
   2195   nbr_sym_iblk = vbn;
   2196 
   2197   /* Write modules and remember their position.  */
   2198   off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE;
   2199 
   2200   if (bfd_seek (arch, off, SEEK_SET) != 0)
   2201     goto err;
   2202 
   2203   for (i = 0; i < nbr_modules; i++)
   2204     {
   2205       struct vms_datadef data;
   2206       unsigned char blk[VMS_BLOCK_SIZE];
   2207       struct vms_mhd *mhd;
   2208       unsigned int sz;
   2209 
   2210       current = modules[i].abfd;
   2211       current->proxy_origin = off;
   2212 
   2213       if (is_elfidx)
   2214 	sz = 0;
   2215       else
   2216 	{
   2217 	  /* Write the MHD as a record (ie, size first).  */
   2218 	  sz = 2;
   2219 	  bfd_putl16 (tdata->mhd_size, blk);
   2220 	}
   2221       mhd = (struct vms_mhd *)(blk + sz);
   2222       memset (mhd, 0, sizeof (struct vms_mhd));
   2223       mhd->lbrflag = 0;
   2224       mhd->id = MHD__C_MHDID;
   2225       mhd->objidlng = 4;
   2226       memcpy (mhd->objid, "V1.0", 4);
   2227       bfd_putl32 (modules[i].ref, mhd->refcnt);
   2228       /* FIXME: datim.  */
   2229 
   2230       sz += tdata->mhd_size;
   2231       sz = (sz + 1) & ~1;
   2232 
   2233       /* Rewind the member to be put into the archive.  */
   2234       if (bfd_seek (current, 0, SEEK_SET) != 0)
   2235 	goto input_err;
   2236 
   2237       /* Copy the member into the archive.  */
   2238       if (is_elfidx)
   2239 	{
   2240 	  unsigned int modsize = 0;
   2241 	  bfd_size_type amt;
   2242 	  file_ptr off_hdr = off;
   2243 
   2244 	  /* Read to complete the first block.  */
   2245 	  amt = bfd_read (blk + sz, VMS_BLOCK_SIZE - sz, current);
   2246 	  if (amt == (bfd_size_type)-1)
   2247 	    goto input_err;
   2248 	  modsize = amt;
   2249 	  if (amt < VMS_BLOCK_SIZE - sz)
   2250 	    {
   2251 	      /* The member size is less than a block.  Pad the block.  */
   2252 	      memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt);
   2253 	    }
   2254 	  bfd_putl32 (modsize, mhd->modsize);
   2255 
   2256 	  /* Write the first block (which contains an mhd).  */
   2257 	  if (bfd_write (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
   2258 	    goto input_err;
   2259 	  off += VMS_BLOCK_SIZE;
   2260 
   2261 	  if (amt == VMS_BLOCK_SIZE - sz)
   2262 	    {
   2263 	      /* Copy the remaining.  */
   2264 	      char buffer[8 * 1024];
   2265 
   2266 	      while (1)
   2267 		{
   2268 		  amt = bfd_read (buffer, sizeof (buffer), current);
   2269 		  if (amt == (bfd_size_type)-1)
   2270 		    goto input_err;
   2271 		  if (amt == 0)
   2272 		    break;
   2273 		  modsize += amt;
   2274 		  if (amt != sizeof (buffer))
   2275 		    {
   2276 		      /* Clear the padding.  */
   2277 		      memset (buffer + amt, 0, sizeof (buffer) - amt);
   2278 		      amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
   2279 		    }
   2280 		  if (bfd_write (buffer, amt, arch) != amt)
   2281 		    goto input_err;
   2282 		  off += amt;
   2283 		}
   2284 
   2285 	      /* Now that the size is known, write the first block (again).  */
   2286 	      bfd_putl32 (modsize, mhd->modsize);
   2287 	      if (bfd_seek (arch, off_hdr, SEEK_SET) != 0
   2288 		  || bfd_write (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
   2289 		goto input_err;
   2290 	      if (bfd_seek (arch, off, SEEK_SET) != 0)
   2291 		goto input_err;
   2292 	    }
   2293 	}
   2294       else
   2295 	{
   2296 	  /* Write the MHD.  */
   2297 	  if (!vms_write_data_block (arch, &data, &off, blk, sz, 0))
   2298 	    goto input_err;
   2299 
   2300 	  /* Write the member.  */
   2301 	  while (1)
   2302 	    {
   2303 	      sz = bfd_read (blk, sizeof (blk), current);
   2304 	      if (sz == 0)
   2305 		break;
   2306 	      if (!vms_write_data_block (arch, &data, &off, blk, sz, 0))
   2307 		goto input_err;
   2308 	    }
   2309 
   2310 	  /* Write the end of module marker.  */
   2311 	  if (!vms_write_data_block (arch, &data, &off,
   2312 				     eotdesc, sizeof (eotdesc), 1))
   2313 	    goto input_err;
   2314 	}
   2315     }
   2316 
   2317   /* Write the indexes.  */
   2318   vbn = 2;
   2319   if (!vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn,
   2320 			is_elfidx))
   2321     goto err;
   2322   if (!vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn,
   2323 			is_elfidx))
   2324     goto err;
   2325 
   2326   /* Write libary header.  */
   2327   {
   2328     unsigned char blk[VMS_BLOCK_SIZE];
   2329     struct vms_lhd *lhd = (struct vms_lhd *)blk;
   2330     struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
   2331     unsigned int idd_flags;
   2332     unsigned int saneid;
   2333 
   2334     memset (blk, 0, sizeof (blk));
   2335 
   2336     lhd->type = tdata->type;
   2337     lhd->nindex = 2;
   2338     switch (tdata->kind)
   2339       {
   2340       case vms_lib_alpha:
   2341 	saneid = LHD_SANEID3;
   2342 	break;
   2343       case vms_lib_ia64:
   2344 	saneid = LHD_SANEID6;
   2345 	break;
   2346       default:
   2347 	abort ();
   2348       }
   2349     bfd_putl32 (saneid, lhd->sanity);
   2350     bfd_putl16 (tdata->ver, lhd->majorid);
   2351     bfd_putl16 (0, lhd->minorid);
   2352     snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
   2353 	      "GNU ar %u.%u.%u",
   2354 	      (unsigned)(BFD_VERSION / 100000000UL),
   2355 	      (unsigned)(BFD_VERSION / 1000000UL) % 100,
   2356 	      (unsigned)(BFD_VERSION / 10000UL) % 100);
   2357     lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
   2358     lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
   2359 
   2360     bfd_putl32 (tdata->credat_lo, lhd->credat + 0);
   2361     bfd_putl32 (tdata->credat_hi, lhd->credat + 4);
   2362     vms_raw_get_time (lhd->updtim);
   2363 
   2364     lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT;
   2365 
   2366     bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
   2367     bfd_putl32 (nbr_modules, lhd->modcnt);
   2368     bfd_putl32 (nbr_modules, lhd->modhdrs);
   2369 
   2370     /* Number of blocks for index.  */
   2371     bfd_putl32 (nbr_mod_iblk + nbr_sym_iblk, lhd->idxblks);
   2372     bfd_putl32 (vbn - 1, lhd->hipreal);
   2373     bfd_putl32 (vbn - 1, lhd->hiprusd);
   2374 
   2375     /* VBN of the next free block.  */
   2376     bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextvbn);
   2377     bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextrfa + 0);
   2378     bfd_putl16 (0, lhd->nextrfa + 4);
   2379 
   2380     /* First index (modules name).  */
   2381     idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX
   2382       | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR;
   2383     bfd_putl16 (idd_flags, idd->flags);
   2384     bfd_putl16 (max_keylen + 1, idd->keylen);
   2385     bfd_putl16 (mod_idx_vbn, idd->vbn);
   2386     idd++;
   2387 
   2388     /* Second index (symbols name).  */
   2389     bfd_putl16 (idd_flags, idd->flags);
   2390     bfd_putl16 (max_keylen + 1, idd->keylen);
   2391     bfd_putl16 (sym_idx_vbn, idd->vbn);
   2392     idd++;
   2393 
   2394     if (!vms_write_block (arch, 1, blk))
   2395       goto err;
   2396   }
   2397 
   2398   free (symbols);
   2399   return true;
   2400 
   2401  input_err:
   2402   bfd_set_input_error (current, bfd_get_error ());
   2403  err:
   2404   free (symbols);
   2405   return false;
   2406 }
   2407 
   2408 /* Add a target for text library.  This costs almost nothing and is useful to
   2409    read VMS library on the host.  */
   2410 
   2411 const bfd_target alpha_vms_lib_txt_vec =
   2412 {
   2413   "vms-libtxt",			/* Name.  */
   2414   bfd_target_unknown_flavour,
   2415   BFD_ENDIAN_UNKNOWN,		/* byteorder */
   2416   BFD_ENDIAN_UNKNOWN,		/* header_byteorder */
   2417   0,				/* Object flags.  */
   2418   0,				/* Sect flags.  */
   2419   0,				/* symbol_leading_char.  */
   2420   ' ',				/* ar_pad_char.  */
   2421   15,				/* ar_max_namelen.  */
   2422   0,				/* match priority.  */
   2423   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
   2424   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
   2425   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
   2426   bfd_getl16, bfd_getl_signed_16, bfd_putl16,
   2427   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
   2428   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
   2429   bfd_getl16, bfd_getl_signed_16, bfd_putl16,
   2430   {				/* bfd_check_format.  */
   2431     _bfd_dummy_target,
   2432     _bfd_dummy_target,
   2433     _bfd_vms_lib_txt_archive_p,
   2434     _bfd_dummy_target
   2435   },
   2436   {				/* bfd_set_format.  */
   2437     _bfd_bool_bfd_false_error,
   2438     _bfd_bool_bfd_false_error,
   2439     _bfd_bool_bfd_false_error,
   2440     _bfd_bool_bfd_false_error
   2441   },
   2442   {				/* bfd_write_contents.  */
   2443     _bfd_bool_bfd_false_error,
   2444     _bfd_bool_bfd_false_error,
   2445     _bfd_bool_bfd_false_error,
   2446     _bfd_bool_bfd_false_error
   2447   },
   2448   BFD_JUMP_TABLE_GENERIC (_bfd_generic),
   2449   BFD_JUMP_TABLE_COPY (_bfd_generic),
   2450   BFD_JUMP_TABLE_CORE (_bfd_nocore),
   2451   BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
   2452   BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
   2453   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
   2454   BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
   2455   BFD_JUMP_TABLE_LINK (_bfd_nolink),
   2456   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
   2457 
   2458   NULL,
   2459 
   2460   NULL
   2461 };
   2462