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