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