Fix whitespace snafu in tc-riscv.c
[binutils-gdb.git] / bfd / vms-lib.c
blobdae95b441f0ac4593219ce972cb5fb9074e71d72
1 /* BFD back-end for VMS archive files.
3 Copyright (C) 2010-2023 Free Software Foundation, Inc.
4 Written by Tristan Gingold <gingold@adacore.com>, AdaCore.
6 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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"
33 /* The standard VMS disk block size. */
34 #ifndef VMS_BLOCK_SIZE
35 #define VMS_BLOCK_SIZE 512
36 #endif
38 /* Maximum key length (which is also the maximum symbol length in archive). */
39 #define MAX_KEYLEN 128
40 #define MAX_EKEYLEN 1024
42 /* DCX Submaps. */
44 struct dcxsbm_desc
46 unsigned char min_char;
47 unsigned char max_char;
48 unsigned char *flags;
49 unsigned char *nodes;
50 unsigned short *next;
53 /* Kind of library. Used to filter in archive_p. */
55 enum vms_lib_kind
57 vms_lib_vax,
58 vms_lib_alpha,
59 vms_lib_ia64,
60 vms_lib_txt
63 /* Back-end private data. */
65 struct lib_tdata
67 /* Standard tdata for an archive. But we don't use many fields. */
68 struct artdata artdata;
70 /* Major version. */
71 unsigned char ver;
73 /* Type of the archive. */
74 unsigned char type;
76 /* Kind of archive. Summary of its type. */
77 enum vms_lib_kind kind;
79 /* Total size of the mhd (element header). */
80 unsigned int mhd_size;
82 /* Creation date. */
83 unsigned int credat_lo;
84 unsigned int credat_hi;
86 /* Vector of modules (archive elements), already sorted. */
87 unsigned int nbr_modules;
88 struct carsym *modules;
89 bfd **cache;
91 /* DCX (decompression) data. */
92 unsigned int nbr_dcxsbm;
93 struct dcxsbm_desc *dcxsbm;
96 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
98 /* End-Of-Text pattern. This is a special record to mark the end of file. */
100 static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
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. */
112 struct carsym_mem
114 /* The table of content. */
115 struct carsym *idx;
117 /* Number of entries used in the table. */
118 unsigned int nbr;
120 /* Maximum number of entries. */
121 unsigned int max;
123 /* Do not allocate more that this number of entries. */
124 unsigned int limit;
126 /* If true, the table was reallocated on the heap. If false, it is still
127 in the BFD's objalloc. */
128 bool realloced;
131 /* Simply add a name to the index. */
133 static bool
134 vms_add_index (struct carsym_mem *cs, char *name,
135 unsigned int idx_vbn, unsigned int idx_off)
137 if (cs->nbr == cs->max)
139 struct carsym *n;
140 size_t amt;
142 if (cs->max > -33u / 2 || cs->max >= cs->limit)
144 bfd_set_error (bfd_error_file_too_big);
145 return false;
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))
152 bfd_set_error (bfd_error_file_too_big);
153 return false;
156 if (!cs->realloced)
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. */
164 else
166 n = bfd_realloc_or_free (cs->idx, amt);
167 if (n == NULL)
168 return false;
170 cs->idx = n;
171 cs->realloced = true;
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;
179 /* Follow all member of a lns list (pointed by RFA) and add indexes for
180 NAME. Return FALSE in case of error. */
182 static bool
183 vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
184 struct vms_rfa *rfa)
186 struct vms_lns lns;
187 unsigned int vbn;
188 file_ptr off;
190 while (1)
192 vbn = bfd_getl32 (rfa->vbn);
193 if (vbn == 0)
194 return true;
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;
202 if (!vms_add_index (cs, name,
203 bfd_getl32 (lns.modrfa.vbn),
204 bfd_getl16 (lns.modrfa.offset)))
205 return false;
207 rfa = &lns.nxtrfa;
211 /* Read block VBN from ABFD and store it into BLK. Return FALSE in case of error. */
213 static bool
214 vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
216 file_ptr off;
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;
223 return true;
226 /* Write the content of BLK to block VBN of ABFD. Return FALSE in case of error. */
228 static bool
229 vms_write_block (bfd *abfd, unsigned int vbn, void *blk)
231 file_ptr off;
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;
238 return true;
241 /* Read index block VBN and put the entry in **IDX (which is updated).
242 If the entry is indirect, recurse. */
244 static bool
245 vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs,
246 unsigned int recur_count)
248 struct vms_indexdef indexdef;
249 file_ptr off;
250 unsigned char *p;
251 unsigned char *endp;
252 unsigned int n;
254 if (recur_count == 100)
256 bfd_set_error (bfd_error_bad_value);
257 return false;
260 /* Read the index block. */
261 BFD_ASSERT (sizeof (indexdef) == VMS_BLOCK_SIZE);
262 if (!vms_read_block (abfd, vbn, &indexdef))
263 return false;
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)
273 unsigned int idx_vbn;
274 unsigned int idx_off;
275 unsigned int keylen;
276 unsigned char *keyname;
277 unsigned int flags;
279 /* Extract key length. */
280 if (bfd_libdata (abfd)->ver == LBR_MAJORID
281 && offsetof (struct vms_idx, keyname) <= (size_t) (endp - p))
283 struct vms_idx *ridx = (struct vms_idx *)p;
285 idx_vbn = bfd_getl32 (ridx->rfa.vbn);
286 idx_off = bfd_getl16 (ridx->rfa.offset);
288 keylen = ridx->keylen;
289 flags = 0;
290 keyname = ridx->keyname;
292 else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID
293 && offsetof (struct vms_elfidx, keyname) <= (size_t) (endp - p))
295 struct vms_elfidx *ridx = (struct vms_elfidx *)p;
297 idx_vbn = bfd_getl32 (ridx->rfa.vbn);
298 idx_off = bfd_getl16 (ridx->rfa.offset);
300 keylen = bfd_getl16 (ridx->keylen);
301 flags = ridx->flags;
302 keyname = ridx->keyname;
304 else
305 return false;
307 /* Illegal value. */
308 if (idx_vbn == 0)
309 return false;
311 /* Point to the next index entry. */
312 p = keyname + keylen;
313 if (p > endp)
314 return false;
316 if (idx_off == RFADEF__C_INDEX)
318 /* Indirect entry. Recurse. */
319 if (!vms_traverse_index (abfd, idx_vbn, cs, recur_count + 1))
320 return false;
322 else
324 /* Add a new entry. */
325 char *name;
327 if (flags & ELFIDX__SYMESC)
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];
336 /* Sanity check. */
337 if (keylen != sizeof (struct vms_kbn))
338 return false;
340 kbn = (struct vms_kbn *)keyname;
341 keylen = bfd_getl16 (kbn->keylen);
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);
349 /* Read the key, chunk by chunk. */
352 unsigned int klen;
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);
365 if (noff + klen > keylen)
366 return false;
367 memcpy (name + noff, kbn + 1, klen);
368 noff += klen;
370 while (kvbn != 0);
372 /* Sanity check. */
373 if (noff != keylen)
374 return false;
376 else
378 /* Usual key name. */
379 name = bfd_alloc (abfd, keylen + 1);
380 if (name == NULL)
381 return false;
383 memcpy (name, keyname, keylen);
385 name[keylen] = 0;
387 if (flags & ELFIDX__LISTRFA)
389 struct vms_lhs lhs;
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;
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;
407 else
409 if (!vms_add_index (cs, name, idx_vbn, idx_off))
410 return false;
415 return true;
418 /* Read index #IDX, which must have NBREL entries. */
420 static struct carsym *
421 vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
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;
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;
436 /* Sanity checks. */
437 flags = bfd_getl16 (idd.flags);
438 if (!(flags & IDD__FLAGS_ASCII)
439 || !(flags & IDD__FLAGS_VARLENIDX))
440 return NULL;
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)
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);
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;
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))
468 if (csm.realloced)
469 free (csm.idx);
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;
477 if (csm.realloced)
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)
484 free (csm.idx);
485 return NULL;
487 memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym));
488 free (csm.idx);
489 csm.idx = csbuf;
491 *nbrel = csm.nbr;
492 return csm.idx;
495 /* Standard function. */
497 static bfd_cleanup
498 _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
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;
508 /* Read header. */
509 if (bfd_read (&lhd, sizeof (lhd), abfd) != sizeof (lhd))
511 if (bfd_get_error () != bfd_error_system_call)
512 bfd_set_error (bfd_error_wrong_format);
513 return NULL;
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))
522 bfd_set_error (bfd_error_wrong_format);
523 return NULL;
525 majorid = bfd_getl32 (lhd.majorid);
527 /* Check archive kind. */
528 switch (kind)
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)
535 bfd_set_error (bfd_error_wrong_format);
536 return NULL;
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)
544 bfd_set_error (bfd_error_wrong_format);
545 return NULL;
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)
555 bfd_set_error (bfd_error_wrong_format);
556 return NULL;
558 break;
559 default:
560 abort ();
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);
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)
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;
596 tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
597 if (tdata->cache == NULL)
598 goto err;
600 /* Read DCX submaps. */
601 dcxvbn = bfd_getl32 (lhd.dcxmapvbn);
602 if (dcxvbn != 0)
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;
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++)
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;
636 if (sbm_off > reclen
637 || reclen - sbm_off < sizeof (struct vms_dcxsbm))
639 err_free_buf:
640 free (buf);
641 goto err;
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;
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)
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);
682 else
684 /* There is no next array if there is only one submap. */
685 BFD_ASSERT (tdata->nbr_dcxsbm == 1);
686 sbmdesc->next = NULL;
689 free (buf);
691 else
693 tdata->nbr_dcxsbm = 0;
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;
701 return _bfd_no_cleanup;
703 err:
704 bfd_release (abfd, tdata);
705 abfd->tdata.any = (void *)tdata_hold;
706 return NULL;
709 /* Standard function for alpha libraries. */
711 bfd_cleanup
712 _bfd_vms_lib_alpha_archive_p (bfd *abfd)
714 return _bfd_vms_lib_archive_p (abfd, vms_lib_alpha);
717 /* Standard function for ia64 libraries. */
719 bfd_cleanup
720 _bfd_vms_lib_ia64_archive_p (bfd *abfd)
722 return _bfd_vms_lib_archive_p (abfd, vms_lib_ia64);
725 /* Standard function for text libraries. */
727 static bfd_cleanup
728 _bfd_vms_lib_txt_archive_p (bfd *abfd)
730 return _bfd_vms_lib_archive_p (abfd, vms_lib_txt);
733 /* Standard bfd function. */
735 static bool
736 _bfd_vms_lib_mkarchive (bfd *abfd, enum vms_lib_kind kind)
738 struct lib_tdata *tdata;
740 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
741 if (tdata == NULL)
742 return false;
744 abfd->tdata.any = (void *)tdata;
745 vms_get_time (&tdata->credat_hi, &tdata->credat_lo);
747 tdata->kind = kind;
748 switch (kind)
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 ();
764 tdata->nbr_modules = 0;
765 tdata->artdata.symdef_count = 0;
766 tdata->modules = NULL;
767 tdata->artdata.symdefs = NULL;
768 tdata->cache = NULL;
770 return true;
773 bool
774 _bfd_vms_lib_alpha_mkarchive (bfd *abfd)
776 return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha);
779 bool
780 _bfd_vms_lib_ia64_mkarchive (bfd *abfd)
782 return _bfd_vms_lib_mkarchive (abfd, vms_lib_ia64);
785 /* Find NAME in the symbol index. Return the index. */
787 symindex
788 _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
790 struct lib_tdata *tdata = bfd_libdata (abfd);
791 carsym *syms = tdata->artdata.symdefs;
792 int lo, hi;
794 /* Open-coded binary search for speed. */
795 lo = 0;
796 hi = tdata->artdata.symdef_count - 1;
798 while (lo <= hi)
800 int mid = lo + (hi - lo) / 2;
801 int diff;
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;
813 return BFD_NO_MORE_SYMBOLS;
816 /* IO vector for archive member. Need that because members are not linearly
817 stored in archives. */
819 struct vms_lib_iovec
821 /* Current offset. */
822 ufile_ptr where;
824 /* Length of the module, when known. */
825 ufile_ptr file_len;
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
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;
845 /* Offset of the first block. Extracted from the index. */
846 file_ptr first_block;
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;
853 /* Used to store any 3 byte record, which could be the EOF pattern. */
854 unsigned char pattern[4];
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;
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;
872 /* Return the current position. */
874 static file_ptr
875 vms_lib_btell (struct bfd *abfd)
877 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
878 return vec->where;
881 /* Read the header of the next data block if all bytes of the current block
882 have been read. */
884 static bool
885 vms_lib_read_block (struct bfd *abfd)
887 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
889 if (vec->blk_off == DATA__LENGTH)
891 unsigned char hdr[DATA__DATA];
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);
901 return true;
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. */
908 static file_ptr
909 vms_lib_bread_raw (struct bfd *abfd, unsigned char *buf, file_ptr nbytes)
911 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
912 file_ptr res;
914 res = 0;
915 while (nbytes > 0)
917 unsigned int l;
919 /* Be sure the current data block is read. */
920 if (!vms_lib_read_block (abfd))
921 return -1;
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)
931 /* Really read into BUF. */
932 if (bfd_read (buf, l, abfd->my_archive) != l)
933 return -1;
935 else
937 /* Make as if we are reading. */
938 if (bfd_seek (abfd->my_archive, l, SEEK_CUR) != 0)
939 return -1;
942 if (buf != NULL)
943 buf += l;
944 vec->blk_off += l;
945 nbytes -= l;
946 res += l;
948 return res;
951 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
953 static file_ptr
954 vms_lib_dcx (struct vms_lib_iovec *vec, unsigned char *buf, file_ptr nbytes)
956 struct dcxsbm_desc *sbm;
957 unsigned int i;
958 unsigned int offset;
959 unsigned int j;
960 file_ptr res = 0;
962 /* The loop below expect to deliver at least one byte. */
963 if (nbytes == 0)
964 return 0;
966 /* Get the current state. */
967 sbm = vec->dcx_sbm;
968 offset = vec->dcx_offset;
969 j = vec->dcx_pos & 7;
971 for (i = vec->dcx_pos >> 3; i < vec->dcx_rlen; i++)
973 unsigned char b = vec->dcx_buf[i];
975 for (; j < 8; j++)
977 if (b & (1 << j))
978 offset++;
979 if (!(sbm->flags[offset >> 3] & (1 << (offset & 7))))
981 unsigned int n_offset = sbm->nodes[offset];
982 if (n_offset == 0)
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;
992 offset = 2 * n_offset;
994 else
996 unsigned char v = sbm->nodes[offset];
998 if (sbm->next != NULL)
999 sbm = vec->dcxsbms + sbm->next[v];
1000 offset = 0;
1001 res++;
1003 if (buf)
1005 *buf++ = v;
1006 nbytes--;
1008 if (nbytes == 0)
1010 vec->dcx_pos = (i << 3) + j + 1;
1011 vec->dcx_offset = offset;
1012 vec->dcx_sbm = sbm;
1014 return res;
1019 j = 0;
1021 return -1;
1024 /* Standard IOVEC function. */
1026 static file_ptr
1027 vms_lib_bread (struct bfd *abfd, void *vbuf, file_ptr nbytes)
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;
1034 /* Do not read past the end. */
1035 if (vec->where >= vec->file_len)
1036 return 0;
1038 res = 0;
1039 while (nbytes > 0)
1041 if (vec->rec_rem == 0)
1043 unsigned char blen[2];
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)
1051 /* Discard record size and align byte. */
1052 vec->rec_pos = 0;
1053 vec->rec_rem = vec->rec_len;
1055 else
1057 /* Prepend record size. */
1058 vec->rec_pos = REC_POS_LEN0;
1059 vec->rec_rem = (vec->rec_len + 1) & ~1; /* With align byte. */
1061 if (vec->rec_len == 3)
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))
1068 /* This is really an EOF. */
1069 vec->where += res;
1070 vec->file_len = vec->where;
1071 return res;
1075 if (vec->dcxsbms != NULL)
1077 /* This is a compressed member. */
1078 unsigned int len;
1079 file_ptr elen;
1081 /* Be sure there is enough room for the expansion. */
1082 len = (vec->rec_len + 1) & ~1;
1083 if (len > vec->dcx_max)
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;
1092 /* Read the compressed record. */
1093 vec->dcx_rlen = len;
1094 if (vec->rec_len == 3)
1096 /* Already read. */
1097 memcpy (vec->dcx_buf, vec->pattern, 3);
1099 else
1101 elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len);
1102 if (elen != len)
1103 return -1;
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;
1116 /* Reset the state. */
1117 vec->dcx_offset = 0;
1118 vec->dcx_sbm = vec->dcxsbms;
1119 vec->dcx_pos = 0;
1122 if (vec->rec_pos < 0)
1124 unsigned char c;
1125 switch (vec->rec_pos)
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 ();
1146 if (buf != NULL)
1148 *buf = c;
1149 buf++;
1151 nbytes--;
1152 res++;
1153 continue;
1156 if (nbytes > vec->rec_rem)
1157 chunk = vec->rec_rem;
1158 else
1159 chunk = nbytes;
1161 if (vec->dcxsbms != NULL)
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);
1168 else
1170 if (vec->rec_len == 3)
1172 if (buf != NULL)
1173 memcpy (buf, vec->pattern + vec->rec_pos, chunk);
1175 else
1176 chunk = vms_lib_bread_raw (abfd, buf, chunk);
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;
1187 if (vec->rec_rem == 0)
1189 /* End of record reached. */
1190 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
1192 if ((vec->rec_len & 1) == 1
1193 && vec->rec_len != 3
1194 && vec->dcxsbms == NULL)
1196 /* Eat the pad byte. */
1197 unsigned char pad;
1198 if (vms_lib_bread_raw (abfd, &pad, 1) != 1)
1199 return -1;
1201 vec->rec_pos = REC_POS_NL;
1202 vec->rec_rem = 1;
1204 else
1206 if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL)
1208 vec->rec_pos = REC_POS_PAD;
1209 vec->rec_rem = 1;
1214 vec->where += res;
1215 return res;
1218 /* Standard function, but we currently only handle the rewind case. */
1220 static int
1221 vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence)
1223 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1225 if (whence == SEEK_SET && offset == 0)
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;
1233 if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0)
1234 return -1;
1236 else
1237 abort ();
1238 return 0;
1241 static file_ptr
1242 vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED,
1243 const void *where ATTRIBUTE_UNUSED,
1244 file_ptr nbytes ATTRIBUTE_UNUSED)
1246 return -1;
1249 static int
1250 vms_lib_bclose (struct bfd *abfd)
1252 abfd->iostream = NULL;
1253 return 0;
1256 static int
1257 vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
1259 return 0;
1262 static int
1263 vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
1264 struct stat *sb ATTRIBUTE_UNUSED)
1266 /* Not supported. */
1267 return 0;
1270 static void *
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)
1280 return (void *) -1;
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
1288 /* Open a library module. FILEPOS is the position of the module header. */
1290 static bool
1291 vms_lib_bopen (bfd *el, file_ptr filepos)
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;
1299 /* Allocate and initialized the iovec. */
1300 vec = bfd_zalloc (el, sizeof (*vec));
1301 if (vec == NULL)
1302 return false;
1304 el->iostream = vec;
1305 el->iovec = &vms_lib_iovec;
1307 /* File length is not known. */
1308 vec->file_len = -1;
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;
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;
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;
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;
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;
1351 if (vec->dcxsbms != NULL)
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;
1360 return true;
1363 /* Get member MODIDX. Return NULL in case of error. */
1365 static bfd *
1366 _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
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;
1375 /* Sanity check. */
1376 if (modidx >= tdata->nbr_modules)
1377 return NULL;
1379 /* Already loaded. */
1380 if (tdata->cache[modidx])
1381 return tdata->cache[modidx];
1383 /* Build it. */
1384 file_off = tdata->modules[modidx].file_offset;
1385 if (tdata->type != LBR__C_TYP_IOBJ)
1387 res = _bfd_create_empty_archive_element_shell (abfd);
1388 if (res == NULL)
1389 return NULL;
1391 /* Special reader to deal with data blocks. */
1392 if (!vms_lib_bopen (res, file_off))
1393 return NULL;
1395 else
1397 char buf[256];
1398 struct vms_mhd *mhd;
1399 struct areltdata *arelt;
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;
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;
1411 mhd = (struct vms_mhd *) buf;
1412 if (mhd->id != MHD__C_MHDID)
1413 return NULL;
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)
1421 bfd_close (res);
1422 return NULL;
1424 res->arelt_data = arelt;
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;
1432 arelt->parsed_size = bfd_getl32 (mhd->modsize);
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;
1439 /* Set filename. */
1440 name = tdata->modules[modidx].name;
1441 namelen = strlen (name);
1442 newname = bfd_malloc (namelen + 4 + 1);
1443 if (newname == NULL)
1445 bfd_close (res);
1446 return NULL;
1448 strcpy (newname, name);
1449 switch (tdata->type)
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;
1459 bfd_set_filename (res, newname);
1460 free (newname);
1461 if (bfd_get_filename (res) == NULL)
1463 bfd_close (res);
1464 return NULL;
1467 tdata->cache[modidx] = res;
1469 return res;
1472 /* Standard function: get member at IDX. */
1474 bfd *
1475 _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
1477 struct lib_tdata *tdata = bfd_libdata (abfd);
1478 file_ptr file_off;
1479 unsigned int modidx;
1481 /* Check symidx. */
1482 if (symidx > tdata->artdata.symdef_count)
1483 return NULL;
1484 file_off = tdata->artdata.symdefs[symidx].file_offset;
1486 /* Linear-scan. */
1487 for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
1489 if (tdata->modules[modidx].file_offset == file_off)
1490 break;
1492 if (modidx >= tdata->nbr_modules)
1493 return NULL;
1495 return _bfd_vms_lib_get_module (abfd, modidx);
1498 /* Elements of an imagelib are stubs. You can get the real image with this
1499 function. */
1501 bfd *
1502 _bfd_vms_lib_get_imagelib_file (bfd *el)
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;
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);
1522 filename = _bfd_append_relative_path (archive, filename);
1523 if (filename == NULL)
1524 return NULL;
1525 res = bfd_openr (filename, NULL);
1527 if (res == NULL)
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;
1536 /* FIXME: put it in a cache ? */
1537 return res;
1540 /* Standard function. */
1542 bfd *
1543 _bfd_vms_lib_openr_next_archived_file (bfd *archive,
1544 bfd *last_file)
1546 unsigned int idx;
1547 bfd *res;
1549 if (!last_file)
1550 idx = 0;
1551 else
1552 idx = last_file->proxy_origin + 1;
1554 if (idx >= bfd_libdata (archive)->nbr_modules)
1556 bfd_set_error (bfd_error_no_more_archived_files);
1557 return NULL;
1560 res = _bfd_vms_lib_get_module (archive, idx);
1561 if (res == NULL)
1562 return res;
1563 res->proxy_origin = idx;
1564 return res;
1567 /* Standard function. Just compute the length. */
1570 _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
1572 struct lib_tdata *tdata;
1574 /* Sanity check. */
1575 if (abfd->my_archive == NULL)
1577 bfd_set_error (bfd_error_invalid_operation);
1578 return -1;
1581 tdata = bfd_libdata (abfd->my_archive);
1582 if (tdata->type != LBR__C_TYP_IOBJ)
1584 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1586 if (vec->file_len == (ufile_ptr)-1)
1588 if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
1589 return -1;
1591 /* Compute length. */
1592 while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
1595 st->st_size = vec->file_len;
1597 else
1599 st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
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;
1610 return 0;
1613 /* Internal representation of an index entry. */
1615 struct lib_index
1617 /* Corresponding archive member. */
1618 bfd *abfd;
1620 /* Number of reference to this entry. */
1621 unsigned int ref;
1623 /* Length of the key. */
1624 unsigned short namlen;
1626 /* Key. */
1627 const char *name;
1630 /* Used to sort index entries. */
1632 static int
1633 lib_index_cmp (const void *lv, const void *rv)
1635 const struct lib_index *l = lv;
1636 const struct lib_index *r = rv;
1638 return strcmp (l->name, r->name);
1641 /* Maximum number of index blocks level. */
1643 #define MAX_LEVEL 10
1645 /* Get the size of an index entry. */
1647 static unsigned int
1648 get_idxlen (struct lib_index *idx, bool is_elfidx)
1650 if (is_elfidx)
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;
1658 else
1660 /* 7 is the size of struct vms_idx without keyname. */
1661 return 7 + idx->namlen;
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. */
1672 static bool
1673 vms_write_index (bfd *abfd,
1674 struct lib_index *idx, unsigned int nbr, unsigned int *vbn,
1675 unsigned int *topvbn, bool is_elfidx)
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
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];
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. */
1701 if (nbr == 0)
1703 /* No entries. Very easy to handle. */
1704 if (topvbn != NULL)
1705 *topvbn = 0;
1706 return true;
1709 if (abfd == NULL)
1711 /* Sort the index the first time this function is called. */
1712 qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp);
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;
1723 for (i = 0; i < nbr; i++, idx++)
1725 unsigned int idxlen;
1726 int flush = 0;
1727 unsigned int key_vbn = 0;
1728 unsigned int key_off = 0;
1730 idxlen = get_idxlen (idx, is_elfidx);
1732 if (is_elfidx && idx->namlen > MAX_KEYLEN)
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;
1739 /* Write the key in the kbn, chunk after chunk. */
1742 if (kbn_sz < sizeof (struct vms_kbn))
1744 /* Not enough room in the kbn block. */
1745 if (abfd != NULL)
1747 /* Write it to the disk (if there is one). */
1748 if (kbn_vbn != 0)
1750 if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
1751 goto err;
1753 else
1755 kbn_blk = bfd_malloc (VMS_BLOCK_SIZE);
1756 if (kbn_blk == NULL)
1757 goto err;
1759 *(unsigned short *)kbn_blk = 0;
1761 /* Allocate a new block for the keys. */
1762 kbn_vbn = (*vbn)++;
1763 kbn_sz = VMS_BLOCK_SIZE - 2;
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;
1771 if (kbn_blk != NULL)
1773 struct vms_kbn *kbn;
1775 kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz);
1777 if (key_vbn == 0)
1779 /* Save the rfa of the first chunk. */
1780 key_vbn = kbn_vbn;
1781 key_off = VMS_BLOCK_SIZE - kbn_sz;
1784 bfd_putl16 (kl_chunk, kbn->keylen);
1785 if (kl_chunk == kl)
1787 /* No next chunk. */
1788 bfd_putl32 (0, kbn->rfa.vbn);
1789 bfd_putl16 (0, kbn->rfa.offset);
1791 else
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);
1797 memcpy ((char *)(kbn + 1), key, kl_chunk);
1798 key += kl_chunk;
1800 kl -= kl_chunk;
1801 kl_chunk = (kl_chunk + 1) & ~1; /* Always align. */
1802 kbn_sz -= kl_chunk + sizeof (struct vms_kbn);
1804 while (kl > 0);
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;
1813 for (j = 0; j < level; j++)
1815 if (j < flush)
1817 /* There is not enough room to write the new entry in this
1818 block or in a parent block. */
1820 if (j + 1 == level)
1822 BFD_ASSERT (level < MAX_LEVEL);
1824 /* Need to create a parent. */
1825 if (abfd != NULL)
1827 rblk[level] = bfd_zmalloc (sizeof (struct vms_indexdef));
1828 bfd_putl32 (*vbn, rblk[j]->parent);
1830 blk[level].vbn = (*vbn)++;
1831 blk[level].len = 0;
1832 blk[level].lastlen = blk[j].lastlen;
1834 level++;
1837 /* Update parent block: write the last entry from the current
1838 block. */
1839 if (abfd != NULL)
1841 struct vms_rfa *rfa;
1843 /* Pointer to the last entry in parent block. */
1844 rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len);
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);
1855 if (j + 1 == flush)
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;
1864 /* Write this block on the disk. */
1865 if (abfd != NULL)
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;
1872 /* Reset this block. */
1873 blk[j].len = 0;
1874 blk[j].lastlen = 0;
1875 blk[j].vbn = (*vbn)++;
1878 /* Append it to the block. */
1879 if (j == 0)
1881 /* Keep the previous last entry. */
1882 blk[j].len += blk[j].lastlen;
1884 if (abfd != NULL)
1886 struct vms_rfa *rfa;
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);
1896 if (is_elfidx)
1898 /* Use elfidx format. */
1899 struct vms_elfidx *en = (struct vms_elfidx *)rfa;
1901 en->flags = 0;
1902 if (key_vbn != 0)
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;
1912 else
1914 bfd_putl16 (idx->namlen, en->keylen);
1915 memcpy (en->keyname, idx->name, idx->namlen);
1918 else
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);
1927 /* The last added key can now be the last one all blocks in the
1928 path. */
1929 blk[j].lastlen = idxlen;
1933 /* Save VBN of the root. */
1934 if (topvbn != NULL)
1935 *topvbn = blk[level - 1].vbn;
1937 if (abfd == NULL)
1938 return true;
1940 /* Flush. */
1941 for (j = 1; j < level; j++)
1943 /* Update parent block: write the new entry. */
1944 unsigned char *en;
1945 unsigned char *par;
1946 struct vms_rfa *rfa;
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);
1957 for (j = 0; j < level; j++)
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;
1964 free (rblk[j]);
1965 rblk[j] = NULL;
1968 /* Write the last kbn (if any). */
1969 if (kbn_vbn != 0)
1971 if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
1972 goto err;
1973 free (kbn_blk);
1976 return true;
1978 err:
1979 if (abfd != NULL)
1981 for (j = 0; j < level; j++)
1982 free (rblk[j]);
1983 free (kbn_blk);
1985 return false;
1988 /* Append data to the data block DATA. Force write if PAD is true. */
1990 static bool
1991 vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off,
1992 const unsigned char *buf, unsigned int len, int pad)
1994 while (len > 0 || pad)
1996 unsigned int doff = *off & (VMS_BLOCK_SIZE - 1);
1997 unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff;
1998 unsigned int l;
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;
2007 if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad))
2009 data->recs = 0;
2010 data->fill_1 = 0;
2011 bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link);
2013 if (bfd_write (data, sizeof (*data), arch) != sizeof (*data))
2014 return false;
2016 *off += DATA__LENGTH - doff;
2018 if (len == 0)
2019 break;
2022 return true;
2025 /* Build the symbols index. */
2027 static bool
2028 _bfd_vms_lib_build_map (unsigned int nbr_modules,
2029 struct lib_index *modules,
2030 unsigned int *res_cnt,
2031 struct lib_index **res)
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;
2040 map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index));
2041 if (map == NULL)
2042 goto error_return;
2044 /* Gather symbols. */
2045 for (i = 0; i < nbr_modules; i++)
2047 long storage;
2048 long symcount;
2049 long src_count;
2050 bfd *current = modules[i].abfd;
2052 if ((bfd_get_file_flags (current) & HAS_SYMS) == 0)
2053 continue;
2055 storage = bfd_get_symtab_upper_bound (current);
2056 if (storage < 0)
2057 goto error_return;
2059 if (storage != 0)
2061 if (storage > syms_max)
2063 free (syms);
2064 syms_max = storage;
2065 syms = (asymbol **) bfd_malloc (syms_max);
2066 if (syms == NULL)
2067 goto error_return;
2069 symcount = bfd_canonicalize_symtab (current, syms);
2070 if (symcount < 0)
2071 goto error_return;
2073 /* Now map over all the symbols, picking out the ones we
2074 want. */
2075 for (src_count = 0; src_count < symcount; src_count++)
2077 flagword flags = (syms[src_count])->flags;
2078 asection *sec = syms[src_count]->section;
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))
2086 struct lib_index *new_map;
2088 /* This symbol will go into the archive header. */
2089 if (map_count == map_max)
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;
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++;
2109 *res_cnt = map_count;
2110 *res = map;
2111 free (syms);
2112 return true;
2114 error_return:
2115 free (syms);
2116 free (map);
2117 return false;
2120 /* Do the hard work: write an archive on the disk. */
2122 bool
2123 _bfd_vms_lib_write_archive_contents (bfd *arch)
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;
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)
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))
2154 bfd_set_error (bfd_error_invalid_operation);
2155 goto input_err;
2158 nbr_modules++;
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;
2167 for (current = arch->archive_head, i = 0;
2168 current != NULL;
2169 current = current->archive_next, i++)
2171 unsigned int nl;
2173 modules[i].abfd = current;
2174 modules[i].name = vms_get_module_name (bfd_get_filename (current), false);
2175 modules[i].ref = 1;
2177 /* FIXME: silently truncate long names ? */
2178 nl = strlen (modules[i].name);
2179 modules[i].namlen = (nl > max_keylen ? max_keylen : nl);
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;
2188 /* Create symbol index. */
2189 if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols))
2190 goto err;
2192 vbn = 0;
2193 if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx))
2194 goto err;
2195 nbr_sym_iblk = vbn;
2197 /* Write modules and remember their position. */
2198 off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE;
2200 if (bfd_seek (arch, off, SEEK_SET) != 0)
2201 goto err;
2203 for (i = 0; i < nbr_modules; i++)
2205 struct vms_datadef data;
2206 unsigned char blk[VMS_BLOCK_SIZE];
2207 struct vms_mhd *mhd;
2208 unsigned int sz;
2210 current = modules[i].abfd;
2211 current->proxy_origin = off;
2213 if (is_elfidx)
2214 sz = 0;
2215 else
2217 /* Write the MHD as a record (ie, size first). */
2218 sz = 2;
2219 bfd_putl16 (tdata->mhd_size, blk);
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. */
2230 sz += tdata->mhd_size;
2231 sz = (sz + 1) & ~1;
2233 /* Rewind the member to be put into the archive. */
2234 if (bfd_seek (current, 0, SEEK_SET) != 0)
2235 goto input_err;
2237 /* Copy the member into the archive. */
2238 if (is_elfidx)
2240 unsigned int modsize = 0;
2241 bfd_size_type amt;
2242 file_ptr off_hdr = off;
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)
2251 /* The member size is less than a block. Pad the block. */
2252 memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt);
2254 bfd_putl32 (modsize, mhd->modsize);
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;
2261 if (amt == VMS_BLOCK_SIZE - sz)
2263 /* Copy the remaining. */
2264 char buffer[8 * 1024];
2266 while (1)
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))
2276 /* Clear the padding. */
2277 memset (buffer + amt, 0, sizeof (buffer) - amt);
2278 amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
2280 if (bfd_write (buffer, amt, arch) != amt)
2281 goto input_err;
2282 off += amt;
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;
2294 else
2296 /* Write the MHD. */
2297 if (!vms_write_data_block (arch, &data, &off, blk, sz, 0))
2298 goto input_err;
2300 /* Write the member. */
2301 while (1)
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;
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;
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;
2326 /* Write libary header. */
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;
2334 memset (blk, 0, sizeof (blk));
2336 lhd->type = tdata->type;
2337 lhd->nindex = 2;
2338 switch (tdata->kind)
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 ();
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);
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);
2364 lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT;
2366 bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
2367 bfd_putl32 (nbr_modules, lhd->modcnt);
2368 bfd_putl32 (nbr_modules, lhd->modhdrs);
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);
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);
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++;
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++;
2394 if (!vms_write_block (arch, 1, blk))
2395 goto err;
2398 free (symbols);
2399 return true;
2401 input_err:
2402 bfd_set_input_error (current, bfd_get_error ());
2403 err:
2404 free (symbols);
2405 return false;
2408 /* Add a target for text library. This costs almost nothing and is useful to
2409 read VMS library on the host. */
2411 const bfd_target alpha_vms_lib_txt_vec =
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
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
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
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),
2458 NULL,
2460 NULL