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