1 /* BFD back-end for VMS archive files.
2 
3    Copyright (C) 2010-2021 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 
44 struct dcxsbm_desc
45 {
46   unsigned char min_char;
47   unsigned char max_char;
48   unsigned char *flags;
49   unsigned char *nodes;
50   unsigned short *next;
51 };
52 
53 /* Kind of library.  Used to filter in archive_p.  */
54 
55 enum vms_lib_kind
56   {
57     vms_lib_vax,
58     vms_lib_alpha,
59     vms_lib_ia64,
60     vms_lib_txt
61   };
62 
63 /* Back-end private data.  */
64 
65 struct lib_tdata
66 {
67   /* Standard tdata for an archive.  But we don't use many fields.  */
68   struct artdata artdata;
69 
70   /* Major version.  */
71   unsigned char ver;
72 
73   /* Type of the archive.  */
74   unsigned char type;
75 
76   /* Kind of archive.  Summary of its type.  */
77   enum vms_lib_kind kind;
78 
79   /* Total size of the mhd (element header).  */
80   unsigned int mhd_size;
81 
82   /* Creation date.  */
83   unsigned int credat_lo;
84   unsigned int credat_hi;
85 
86   /* Vector of modules (archive elements), already sorted.  */
87   unsigned int nbr_modules;
88   struct carsym *modules;
89   bfd **cache;
90 
91   /* DCX (decompression) data.  */
92   unsigned int nbr_dcxsbm;
93   struct dcxsbm_desc *dcxsbm;
94 };
95 
96 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
97 
98 /* End-Of-Text pattern.  This is a special record to mark the end of file.  */
99 
100 static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
101 
102 /* Describe the current state of carsym entries while building the archive
103    table of content.  Things are simple with Alpha archives as the number
104    of entries is known, but with IA64 archives a entry can make a reference
105    to severals members.  Therefore we must be able to extend the table on the
106    fly, but it should be allocated on the bfd - which doesn't support realloc.
107    To reduce the overhead, the table is initially allocated in the BFD's
108    objalloc and extended if necessary on the heap.  In the later case, it
109    is finally copied to the BFD's objalloc so that it will automatically be
110    freed.  */
111 
112 struct carsym_mem
113 {
114   /* The table of content.  */
115   struct carsym *idx;
116 
117   /* Number of entries used in the table.  */
118   unsigned int nbr;
119 
120   /* Maximum number of entries.  */
121   unsigned int max;
122 
123   /* Do not allocate more that this number of entries.  */
124   unsigned int limit;
125 
126   /* If true, the table was reallocated on the heap.  If false, it is still
127      in the BFD's objalloc.  */
128   bool realloced;
129 };
130 
131 /* Simply add a name to the index.  */
132 
133 static bool
vms_add_index(struct carsym_mem * cs,char * name,unsigned int idx_vbn,unsigned int idx_off)134 vms_add_index (struct carsym_mem *cs, char *name,
135 	       unsigned int idx_vbn, unsigned int idx_off)
136 {
137   if (cs->nbr == cs->max)
138     {
139       struct carsym *n;
140       size_t amt;
141 
142       if (cs->max > -33u / 2 || cs->max >= cs->limit)
143 	{
144 	  bfd_set_error (bfd_error_file_too_big);
145 	  return false;
146 	}
147       cs->max = 2 * cs->max + 32;
148       if (cs->max > cs->limit)
149 	cs->max = cs->limit;
150       if (_bfd_mul_overflow (cs->max, sizeof (struct carsym), &amt))
151 	{
152 	  bfd_set_error (bfd_error_file_too_big);
153 	  return false;
154 	}
155 
156       if (!cs->realloced)
157 	{
158 	  n = bfd_malloc (amt);
159 	  if (n == NULL)
160 	    return false;
161 	  memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym));
162 	  /* And unfortunately we can't free cs->idx.  */
163 	}
164       else
165 	{
166 	  n = bfd_realloc_or_free (cs->idx, amt);
167 	  if (n == NULL)
168 	    return false;
169 	}
170       cs->idx = n;
171       cs->realloced = true;
172     }
173   cs->idx[cs->nbr].file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
174   cs->idx[cs->nbr].name = name;
175   cs->nbr++;
176   return true;
177 }
178 
179 /* Follow all member of a lns list (pointed by RFA) and add indexes for
180    NAME.  Return FALSE in case of error.  */
181 
182 static bool
vms_add_indexes_from_list(bfd * abfd,struct carsym_mem * cs,char * name,struct vms_rfa * rfa)183 vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
184 			   struct vms_rfa *rfa)
185 {
186   struct vms_lns lns;
187   unsigned int vbn;
188   file_ptr off;
189 
190   while (1)
191     {
192       vbn = bfd_getl32 (rfa->vbn);
193       if (vbn == 0)
194 	return true;
195 
196       /* Read the LHS.  */
197       off = (vbn - 1) * VMS_BLOCK_SIZE + bfd_getl16 (rfa->offset);
198       if (bfd_seek (abfd, off, SEEK_SET) != 0
199 	  || bfd_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 
213 static bool
vms_read_block(bfd * abfd,unsigned int vbn,void * blk)214 vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
215 {
216   file_ptr off;
217 
218   off = (vbn - 1) * VMS_BLOCK_SIZE;
219   if (bfd_seek (abfd, off, SEEK_SET) != 0
220       || bfd_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 
228 static bool
vms_write_block(bfd * abfd,unsigned int vbn,void * blk)229 vms_write_block (bfd *abfd, unsigned int vbn, void *blk)
230 {
231   file_ptr off;
232 
233   off = (vbn - 1) * VMS_BLOCK_SIZE;
234   if (bfd_seek (abfd, off, SEEK_SET) != 0
235       || bfd_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 
244 static bool
vms_traverse_index(bfd * abfd,unsigned int vbn,struct carsym_mem * cs,unsigned int recur_count)245 vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs,
246 		    unsigned int recur_count)
247 {
248   struct vms_indexdef indexdef;
249   file_ptr off;
250   unsigned char *p;
251   unsigned char *endp;
252   unsigned int n;
253 
254   if (recur_count == 100)
255     {
256       bfd_set_error (bfd_error_bad_value);
257       return false;
258     }
259 
260   /* Read the index block.  */
261   BFD_ASSERT (sizeof (indexdef) == VMS_BLOCK_SIZE);
262   if (!vms_read_block (abfd, vbn, &indexdef))
263     return false;
264 
265   /* Traverse it.  */
266   p = &indexdef.keys[0];
267   n = bfd_getl16 (indexdef.used);
268   if (n > sizeof (indexdef.keys))
269     return false;
270   endp = p + n;
271   while (p < endp)
272     {
273       unsigned int idx_vbn;
274       unsigned int idx_off;
275       unsigned int keylen;
276       unsigned char *keyname;
277       unsigned int flags;
278 
279       /* Extract key length.  */
280       if (bfd_libdata (abfd)->ver == LBR_MAJORID
281 	  && offsetof (struct vms_idx, keyname) <= (size_t) (endp - p))
282 	{
283 	  struct vms_idx *ridx = (struct vms_idx *)p;
284 
285 	  idx_vbn = bfd_getl32 (ridx->rfa.vbn);
286 	  idx_off = bfd_getl16 (ridx->rfa.offset);
287 
288 	  keylen = ridx->keylen;
289 	  flags = 0;
290 	  keyname = ridx->keyname;
291 	}
292       else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID
293 	       && offsetof (struct vms_elfidx, keyname) <= (size_t) (endp - p))
294 	{
295 	  struct vms_elfidx *ridx = (struct vms_elfidx *)p;
296 
297 	  idx_vbn = bfd_getl32 (ridx->rfa.vbn);
298 	  idx_off = bfd_getl16 (ridx->rfa.offset);
299 
300 	  keylen = bfd_getl16 (ridx->keylen);
301 	  flags = ridx->flags;
302 	  keyname = ridx->keyname;
303 	}
304       else
305 	return false;
306 
307       /* Illegal value.  */
308       if (idx_vbn == 0)
309 	return false;
310 
311       /* Point to the next index entry.  */
312       p = keyname + keylen;
313       if (p > endp)
314 	return false;
315 
316       if (idx_off == RFADEF__C_INDEX)
317 	{
318 	  /* Indirect entry.  Recurse.  */
319 	  if (!vms_traverse_index (abfd, idx_vbn, cs, recur_count + 1))
320 	    return false;
321 	}
322       else
323 	{
324 	  /* Add a new entry.  */
325 	  char *name;
326 
327 	  if (flags & ELFIDX__SYMESC)
328 	    {
329 	      /* Extended key name.  */
330 	      unsigned int noff = 0;
331 	      unsigned int koff;
332 	      unsigned int kvbn;
333 	      struct vms_kbn *kbn;
334 	      unsigned char kblk[VMS_BLOCK_SIZE];
335 
336 	      /* Sanity check.  */
337 	      if (keylen != sizeof (struct vms_kbn))
338 		return false;
339 
340 	      kbn = (struct vms_kbn *)keyname;
341 	      keylen = bfd_getl16 (kbn->keylen);
342 
343 	      name = bfd_alloc (abfd, keylen + 1);
344 	      if (name == NULL)
345 		return false;
346 	      kvbn = bfd_getl32 (kbn->rfa.vbn);
347 	      koff = bfd_getl16 (kbn->rfa.offset);
348 
349 	      /* Read the key, chunk by chunk.  */
350 	      do
351 		{
352 		  unsigned int klen;
353 
354 		  if (!vms_read_block (abfd, kvbn, kblk))
355 		    return false;
356 		  if (koff > sizeof (kblk) - sizeof (struct vms_kbn))
357 		    return false;
358 		  kbn = (struct vms_kbn *)(kblk + koff);
359 		  klen = bfd_getl16 (kbn->keylen);
360 		  if (klen > sizeof (kblk) - sizeof (struct vms_kbn) - koff)
361 		    return false;
362 		  kvbn = bfd_getl32 (kbn->rfa.vbn);
363 		  koff = bfd_getl16 (kbn->rfa.offset);
364 
365 		  if (noff + klen > keylen)
366 		    return false;
367 		  memcpy (name + noff, kbn + 1, klen);
368 		  noff += klen;
369 		}
370 	      while (kvbn != 0);
371 
372 	      /* Sanity check.  */
373 	      if (noff != keylen)
374 		return false;
375 	    }
376 	  else
377 	    {
378 	      /* Usual key name.  */
379 	      name = bfd_alloc (abfd, keylen + 1);
380 	      if (name == NULL)
381 		return false;
382 
383 	      memcpy (name, keyname, keylen);
384 	    }
385 	  name[keylen] = 0;
386 
387 	  if (flags & ELFIDX__LISTRFA)
388 	    {
389 	      struct vms_lhs lhs;
390 
391 	      /* Read the LHS.  */
392 	      off = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
393 	      if (bfd_seek (abfd, off, SEEK_SET) != 0
394 		  || bfd_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 
420 static struct carsym *
vms_lib_read_index(bfd * abfd,int idx,unsigned int * nbrel)421 vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
422 {
423   struct vms_idd idd;
424   unsigned int flags;
425   unsigned int vbn;
426   ufile_ptr filesize;
427   size_t amt;
428   struct carsym *csbuf;
429   struct carsym_mem csm;
430 
431   /* Read index desription.  */
432   if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0
433       || bfd_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 
494 static bfd_cleanup
_bfd_vms_lib_archive_p(bfd * abfd,enum vms_lib_kind kind)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 
708 bfd_cleanup
_bfd_vms_lib_alpha_archive_p(bfd * abfd)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 
716 bfd_cleanup
_bfd_vms_lib_ia64_archive_p(bfd * abfd)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 
724 static bfd_cleanup
_bfd_vms_lib_txt_archive_p(bfd * abfd)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 
732 static bool
_bfd_vms_lib_mkarchive(bfd * abfd,enum vms_lib_kind kind)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 
770 bool
_bfd_vms_lib_alpha_mkarchive(bfd * abfd)771 _bfd_vms_lib_alpha_mkarchive (bfd *abfd)
772 {
773   return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha);
774 }
775 
776 bool
_bfd_vms_lib_ia64_mkarchive(bfd * abfd)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 
784 symindex
_bfd_vms_lib_find_symbol(bfd * abfd,const char * name)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 
816 struct 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 
871 static file_ptr
vms_lib_btell(struct bfd * abfd)872 vms_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 
881 static bool
vms_lib_read_block(struct bfd * abfd)882 vms_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 
905 static file_ptr
vms_lib_bread_raw(struct bfd * abfd,unsigned char * buf,file_ptr nbytes)906 vms_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 
950 static file_ptr
vms_lib_dcx(struct vms_lib_iovec * vec,unsigned char * buf,file_ptr nbytes)951 vms_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 
1023 static file_ptr
vms_lib_bread(struct bfd * abfd,void * vbuf,file_ptr nbytes)1024 vms_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 
1217 static int
vms_lib_bseek(struct bfd * abfd,file_ptr offset,int whence)1218 vms_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 
1238 static file_ptr
vms_lib_bwrite(struct bfd * abfd ATTRIBUTE_UNUSED,const void * where ATTRIBUTE_UNUSED,file_ptr nbytes ATTRIBUTE_UNUSED)1239 vms_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 
1246 static int
vms_lib_bclose(struct bfd * abfd)1247 vms_lib_bclose (struct bfd *abfd)
1248 {
1249   abfd->iostream = NULL;
1250   return 0;
1251 }
1252 
1253 static int
vms_lib_bflush(struct bfd * abfd ATTRIBUTE_UNUSED)1254 vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
1255 {
1256   return 0;
1257 }
1258 
1259 static int
vms_lib_bstat(struct bfd * abfd ATTRIBUTE_UNUSED,struct stat * sb ATTRIBUTE_UNUSED)1260 vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
1261 	       struct stat *sb ATTRIBUTE_UNUSED)
1262 {
1263   /* Not supported.  */
1264   return 0;
1265 }
1266 
1267 static void *
vms_lib_bmmap(struct bfd * abfd ATTRIBUTE_UNUSED,void * addr ATTRIBUTE_UNUSED,bfd_size_type len ATTRIBUTE_UNUSED,int prot ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,file_ptr offset ATTRIBUTE_UNUSED,void ** map_addr ATTRIBUTE_UNUSED,bfd_size_type * map_len ATTRIBUTE_UNUSED)1268 vms_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 
1280 static 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 
1287 static bool
vms_lib_bopen(bfd * el,file_ptr filepos)1288 vms_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 
1362 static bfd *
_bfd_vms_lib_get_module(bfd * abfd,unsigned int modidx)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 
1471 bfd *
_bfd_vms_lib_get_elt_at_index(bfd * abfd,symindex symidx)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 
1498 bfd *
_bfd_vms_lib_get_imagelib_file(bfd * el)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 
1539 bfd *
_bfd_vms_lib_openr_next_archived_file(bfd * archive,bfd * last_file)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 
1566 int
_bfd_vms_lib_generic_stat_arch_elt(bfd * abfd,struct stat * st)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 
1612 struct 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 
1629 static int
lib_index_cmp(const void * lv,const void * rv)1630 lib_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 
1644 static unsigned int
get_idxlen(struct lib_index * idx,bool is_elfidx)1645 get_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 
1669 static bool
vms_write_index(bfd * abfd,struct lib_index * idx,unsigned int nbr,unsigned int * vbn,unsigned int * topvbn,bool is_elfidx)1670 vms_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 
1977 static bool
vms_write_data_block(bfd * arch,struct vms_datadef * data,file_ptr * off,const unsigned char * buf,unsigned int len,int pad)1978 vms_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 
2014 static bool
_bfd_vms_lib_build_map(unsigned int nbr_modules,struct lib_index * modules,unsigned int * res_cnt,struct lib_index ** res)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 
2108 bool
_bfd_vms_lib_write_archive_contents(bfd * arch)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 
2394 const 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