Prevent the ASCII linker script directive from generating huge amounts of padding...
[binutils-gdb.git] / bfd / vms-lib.c
blob907d0fa75dc7e1b722aa1d039cd2603b4a3df2f3
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_bread (&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_bread (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_bwrite (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_bread (&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_bread (&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)
483 return NULL;
484 memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym));
485 free (csm.idx);
486 csm.idx = csbuf;
488 *nbrel = csm.nbr;
489 return csm.idx;
492 /* Standard function. */
494 static bfd_cleanup
495 _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
497 struct vms_lhd lhd;
498 unsigned int sanity;
499 unsigned int majorid;
500 struct lib_tdata *tdata_hold;
501 struct lib_tdata *tdata;
502 unsigned int dcxvbn;
503 unsigned int nbr_ent;
505 /* Read header. */
506 if (bfd_bread (&lhd, sizeof (lhd), abfd) != sizeof (lhd))
508 if (bfd_get_error () != bfd_error_system_call)
509 bfd_set_error (bfd_error_wrong_format);
510 return NULL;
513 /* Check sanity (= magic) number. */
514 sanity = bfd_getl32 (lhd.sanity);
515 if (!(sanity == LHD_SANEID3
516 || sanity == LHD_SANEID6
517 || sanity == LHD_SANEID_DCX))
519 bfd_set_error (bfd_error_wrong_format);
520 return NULL;
522 majorid = bfd_getl32 (lhd.majorid);
524 /* Check archive kind. */
525 switch (kind)
527 case vms_lib_alpha:
528 if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB)
529 || majorid != LBR_MAJORID
530 || lhd.nindex != 2)
532 bfd_set_error (bfd_error_wrong_format);
533 return NULL;
535 break;
536 case vms_lib_ia64:
537 if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB)
538 || majorid != LBR_ELFMAJORID
539 || lhd.nindex != 2)
541 bfd_set_error (bfd_error_wrong_format);
542 return NULL;
544 break;
545 case vms_lib_txt:
546 if ((lhd.type != LBR__C_TYP_TXT
547 && lhd.type != LBR__C_TYP_MLB
548 && lhd.type != LBR__C_TYP_HLP)
549 || majorid != LBR_MAJORID
550 || lhd.nindex != 1)
552 bfd_set_error (bfd_error_wrong_format);
553 return NULL;
555 break;
556 default:
557 abort ();
560 /* Allocate and initialize private data. */
561 tdata_hold = bfd_libdata (abfd);
562 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
563 if (tdata == NULL)
564 return NULL;
565 abfd->tdata.any = (void *)tdata;
566 tdata->ver = majorid;
567 tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz;
568 tdata->type = lhd.type;
569 tdata->kind = kind;
570 tdata->credat_lo = bfd_getl32 (lhd.credat + 0);
571 tdata->credat_hi = bfd_getl32 (lhd.credat + 4);
573 /* Read indexes. */
574 tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
575 tdata->artdata.symdef_count = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules;
576 nbr_ent = tdata->nbr_modules;
577 tdata->modules = vms_lib_read_index (abfd, 0, &nbr_ent);
578 if (tdata->modules == NULL || nbr_ent != tdata->nbr_modules)
579 goto err;
580 if (lhd.nindex == 2)
582 nbr_ent = tdata->artdata.symdef_count;
583 tdata->artdata.symdefs = vms_lib_read_index (abfd, 1, &nbr_ent);
584 if (tdata->artdata.symdefs == NULL)
585 goto err;
586 /* Only IA64 archives may have more entries in the index that what
587 was declared. */
588 if (nbr_ent != tdata->artdata.symdef_count
589 && kind != vms_lib_ia64)
590 goto err;
591 tdata->artdata.symdef_count = nbr_ent;
593 tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
594 if (tdata->cache == NULL)
595 goto err;
597 /* Read DCX submaps. */
598 dcxvbn = bfd_getl32 (lhd.dcxmapvbn);
599 if (dcxvbn != 0)
601 unsigned char buf_reclen[4];
602 unsigned int reclen;
603 unsigned char *buf;
604 struct vms_dcxmap *map;
605 unsigned int sbm_off;
606 unsigned int i;
608 if (bfd_seek (abfd, (dcxvbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) != 0
609 || bfd_bread (buf_reclen, sizeof (buf_reclen), abfd)
610 != sizeof (buf_reclen))
611 goto err;
612 reclen = bfd_getl32 (buf_reclen);
613 if (reclen < sizeof (struct vms_dcxmap))
614 goto err;
615 buf = _bfd_malloc_and_read (abfd, reclen, reclen);
616 if (buf == NULL)
617 goto err;
618 map = (struct vms_dcxmap *)buf;
619 tdata->nbr_dcxsbm = bfd_getl16 (map->nsubs);
620 sbm_off = bfd_getl16 (map->sub0);
621 tdata->dcxsbm = (struct dcxsbm_desc *)bfd_alloc
622 (abfd, tdata->nbr_dcxsbm * sizeof (struct dcxsbm_desc));
623 for (i = 0; i < tdata->nbr_dcxsbm; i++)
625 struct vms_dcxsbm *sbm;
626 struct dcxsbm_desc *sbmdesc = &tdata->dcxsbm[i];
627 unsigned int sbm_len;
628 unsigned int sbm_sz;
629 unsigned int off;
630 unsigned char *buf1;
631 unsigned int l, j;
633 if (sbm_off > reclen
634 || reclen - sbm_off < sizeof (struct vms_dcxsbm))
636 err_free_buf:
637 free (buf);
638 goto err;
640 sbm = (struct vms_dcxsbm *) (buf + sbm_off);
641 sbm_sz = bfd_getl16 (sbm->size);
642 sbm_off += sbm_sz;
643 if (sbm_off > reclen)
644 goto err_free_buf;
646 sbmdesc->min_char = sbm->min_char;
647 BFD_ASSERT (sbmdesc->min_char == 0);
648 sbmdesc->max_char = sbm->max_char;
649 sbm_len = sbmdesc->max_char - sbmdesc->min_char + 1;
650 l = (2 * sbm_len + 7) / 8;
651 if (sbm_sz < sizeof (struct vms_dcxsbm) + l + sbm_len
652 || (tdata->nbr_dcxsbm > 1
653 && sbm_sz < sizeof (struct vms_dcxsbm) + l + 3 * sbm_len))
654 goto err_free_buf;
655 sbmdesc->flags = (unsigned char *)bfd_alloc (abfd, l);
656 off = bfd_getl16 (sbm->flags);
657 if (off > sbm_sz
658 || sbm_sz - off < l)
659 goto err_free_buf;
660 memcpy (sbmdesc->flags, (bfd_byte *) sbm + off, l);
661 sbmdesc->nodes = (unsigned char *)bfd_alloc (abfd, 2 * sbm_len);
662 off = bfd_getl16 (sbm->nodes);
663 if (off > sbm_sz
664 || sbm_sz - off < 2 * sbm_len)
665 goto err_free_buf;
666 memcpy (sbmdesc->nodes, (bfd_byte *) sbm + off, 2 * sbm_len);
667 off = bfd_getl16 (sbm->next);
668 if (off != 0)
670 if (off > sbm_sz
671 || sbm_sz - off < 2 * sbm_len)
672 goto err_free_buf;
673 /* Read the 'next' array. */
674 sbmdesc->next = (unsigned short *) bfd_alloc (abfd, 2 * sbm_len);
675 buf1 = (bfd_byte *) sbm + off;
676 for (j = 0; j < sbm_len; j++)
677 sbmdesc->next[j] = bfd_getl16 (buf1 + j * 2);
679 else
681 /* There is no next array if there is only one submap. */
682 BFD_ASSERT (tdata->nbr_dcxsbm == 1);
683 sbmdesc->next = NULL;
686 free (buf);
688 else
690 tdata->nbr_dcxsbm = 0;
693 /* The map is always present. Also mark shared image library. */
694 abfd->has_armap = true;
695 if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB)
696 abfd->is_thin_archive = true;
698 return _bfd_no_cleanup;
700 err:
701 bfd_release (abfd, tdata);
702 abfd->tdata.any = (void *)tdata_hold;
703 return NULL;
706 /* Standard function for alpha libraries. */
708 bfd_cleanup
709 _bfd_vms_lib_alpha_archive_p (bfd *abfd)
711 return _bfd_vms_lib_archive_p (abfd, vms_lib_alpha);
714 /* Standard function for ia64 libraries. */
716 bfd_cleanup
717 _bfd_vms_lib_ia64_archive_p (bfd *abfd)
719 return _bfd_vms_lib_archive_p (abfd, vms_lib_ia64);
722 /* Standard function for text libraries. */
724 static bfd_cleanup
725 _bfd_vms_lib_txt_archive_p (bfd *abfd)
727 return _bfd_vms_lib_archive_p (abfd, vms_lib_txt);
730 /* Standard bfd function. */
732 static bool
733 _bfd_vms_lib_mkarchive (bfd *abfd, enum vms_lib_kind kind)
735 struct lib_tdata *tdata;
737 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
738 if (tdata == NULL)
739 return false;
741 abfd->tdata.any = (void *)tdata;
742 vms_get_time (&tdata->credat_hi, &tdata->credat_lo);
744 tdata->kind = kind;
745 switch (kind)
747 case vms_lib_alpha:
748 tdata->ver = LBR_MAJORID;
749 tdata->mhd_size = offsetof (struct vms_mhd, pad1);
750 tdata->type = LBR__C_TYP_EOBJ;
751 break;
752 case vms_lib_ia64:
753 tdata->ver = LBR_ELFMAJORID;
754 tdata->mhd_size = sizeof (struct vms_mhd);
755 tdata->type = LBR__C_TYP_IOBJ;
756 break;
757 default:
758 abort ();
761 tdata->nbr_modules = 0;
762 tdata->artdata.symdef_count = 0;
763 tdata->modules = NULL;
764 tdata->artdata.symdefs = NULL;
765 tdata->cache = NULL;
767 return true;
770 bool
771 _bfd_vms_lib_alpha_mkarchive (bfd *abfd)
773 return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha);
776 bool
777 _bfd_vms_lib_ia64_mkarchive (bfd *abfd)
779 return _bfd_vms_lib_mkarchive (abfd, vms_lib_ia64);
782 /* Find NAME in the symbol index. Return the index. */
784 symindex
785 _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
787 struct lib_tdata *tdata = bfd_libdata (abfd);
788 carsym *syms = tdata->artdata.symdefs;
789 int lo, hi;
791 /* Open-coded binary search for speed. */
792 lo = 0;
793 hi = tdata->artdata.symdef_count - 1;
795 while (lo <= hi)
797 int mid = lo + (hi - lo) / 2;
798 int diff;
800 diff = (char)(name[0] - syms[mid].name[0]);
801 if (diff == 0)
802 diff = strcmp (name, syms[mid].name);
803 if (diff == 0)
804 return mid;
805 else if (diff < 0)
806 hi = mid - 1;
807 else
808 lo = mid + 1;
810 return BFD_NO_MORE_SYMBOLS;
813 /* IO vector for archive member. Need that because members are not linearly
814 stored in archives. */
816 struct vms_lib_iovec
818 /* Current offset. */
819 ufile_ptr where;
821 /* Length of the module, when known. */
822 ufile_ptr file_len;
824 /* Current position in the record from bfd_bread point of view (ie, after
825 decompression). 0 means that no data byte have been read, -2 and -1
826 are reserved for the length word. */
827 int rec_pos;
828 #define REC_POS_NL -4
829 #define REC_POS_PAD -3
830 #define REC_POS_LEN0 -2
831 #define REC_POS_LEN1 -1
833 /* Record length. */
834 unsigned short rec_len;
835 /* Number of bytes to read in the current record. */
836 unsigned short rec_rem;
837 /* Offset of the next block. */
838 file_ptr next_block;
839 /* Current *data* offset in the data block. */
840 unsigned short blk_off;
842 /* Offset of the first block. Extracted from the index. */
843 file_ptr first_block;
845 /* Initial next_block. Extracted when the MHD is read. */
846 file_ptr init_next_block;
847 /* Initial blk_off, once the MHD is read. */
848 unsigned short init_blk_off;
850 /* Used to store any 3 byte record, which could be the EOF pattern. */
851 unsigned char pattern[4];
853 /* DCX. */
854 struct dcxsbm_desc *dcxsbms;
855 /* Current submap. */
856 struct dcxsbm_desc *dcx_sbm;
857 /* Current offset in the submap. */
858 unsigned int dcx_offset;
859 int dcx_pos;
861 /* Compressed buffer. */
862 unsigned char *dcx_buf;
863 /* Size of the buffer. Used to resize. */
864 unsigned int dcx_max;
865 /* Number of valid bytes in the buffer. */
866 unsigned int dcx_rlen;
869 /* Return the current position. */
871 static file_ptr
872 vms_lib_btell (struct bfd *abfd)
874 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
875 return vec->where;
878 /* Read the header of the next data block if all bytes of the current block
879 have been read. */
881 static bool
882 vms_lib_read_block (struct bfd *abfd)
884 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
886 if (vec->blk_off == DATA__LENGTH)
888 unsigned char hdr[DATA__DATA];
890 /* Read next block. */
891 if (bfd_seek (abfd->my_archive, vec->next_block, SEEK_SET) != 0)
892 return false;
893 if (bfd_bread (hdr, sizeof (hdr), abfd->my_archive) != sizeof (hdr))
894 return false;
895 vec->next_block = (bfd_getl32 (hdr + 2) - 1) * VMS_BLOCK_SIZE;
896 vec->blk_off = sizeof (hdr);
898 return true;
901 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
902 not stored. Read linearly from the library, but handle blocks. This
903 function does not handle records nor EOF. */
905 static file_ptr
906 vms_lib_bread_raw (struct bfd *abfd, unsigned char *buf, file_ptr nbytes)
908 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
909 file_ptr res;
911 res = 0;
912 while (nbytes > 0)
914 unsigned int l;
916 /* Be sure the current data block is read. */
917 if (!vms_lib_read_block (abfd))
918 return -1;
920 /* Do not read past the data block, do not read more than requested. */
921 l = DATA__LENGTH - vec->blk_off;
922 if (l > nbytes)
923 l = nbytes;
924 if (l == 0)
925 return 0;
926 if (buf != NULL)
928 /* Really read into BUF. */
929 if (bfd_bread (buf, l, abfd->my_archive) != l)
930 return -1;
932 else
934 /* Make as if we are reading. */
935 if (bfd_seek (abfd->my_archive, l, SEEK_CUR) != 0)
936 return -1;
939 if (buf != NULL)
940 buf += l;
941 vec->blk_off += l;
942 nbytes -= l;
943 res += l;
945 return res;
948 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
950 static file_ptr
951 vms_lib_dcx (struct vms_lib_iovec *vec, unsigned char *buf, file_ptr nbytes)
953 struct dcxsbm_desc *sbm;
954 unsigned int i;
955 unsigned int offset;
956 unsigned int j;
957 file_ptr res = 0;
959 /* The loop below expect to deliver at least one byte. */
960 if (nbytes == 0)
961 return 0;
963 /* Get the current state. */
964 sbm = vec->dcx_sbm;
965 offset = vec->dcx_offset;
966 j = vec->dcx_pos & 7;
968 for (i = vec->dcx_pos >> 3; i < vec->dcx_rlen; i++)
970 unsigned char b = vec->dcx_buf[i];
972 for (; j < 8; j++)
974 if (b & (1 << j))
975 offset++;
976 if (!(sbm->flags[offset >> 3] & (1 << (offset & 7))))
978 unsigned int n_offset = sbm->nodes[offset];
979 if (n_offset == 0)
981 /* End of buffer. Stay where we are. */
982 vec->dcx_pos = (i << 3) + j;
983 if (b & (1 << j))
984 offset--;
985 vec->dcx_offset = offset;
986 vec->dcx_sbm = sbm;
987 return res;
989 offset = 2 * n_offset;
991 else
993 unsigned char v = sbm->nodes[offset];
995 if (sbm->next != NULL)
996 sbm = vec->dcxsbms + sbm->next[v];
997 offset = 0;
998 res++;
1000 if (buf)
1002 *buf++ = v;
1003 nbytes--;
1005 if (nbytes == 0)
1007 vec->dcx_pos = (i << 3) + j + 1;
1008 vec->dcx_offset = offset;
1009 vec->dcx_sbm = sbm;
1011 return res;
1016 j = 0;
1018 return -1;
1021 /* Standard IOVEC function. */
1023 static file_ptr
1024 vms_lib_bread (struct bfd *abfd, void *vbuf, file_ptr nbytes)
1026 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1027 file_ptr res;
1028 file_ptr chunk;
1029 unsigned char *buf = (unsigned char *)vbuf;
1031 /* Do not read past the end. */
1032 if (vec->where >= vec->file_len)
1033 return 0;
1035 res = 0;
1036 while (nbytes > 0)
1038 if (vec->rec_rem == 0)
1040 unsigned char blen[2];
1042 /* Read record length. */
1043 if (vms_lib_bread_raw (abfd, blen, sizeof (blen)) != sizeof (blen))
1044 return -1;
1045 vec->rec_len = bfd_getl16 (blen);
1046 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
1048 /* Discard record size and align byte. */
1049 vec->rec_pos = 0;
1050 vec->rec_rem = vec->rec_len;
1052 else
1054 /* Prepend record size. */
1055 vec->rec_pos = REC_POS_LEN0;
1056 vec->rec_rem = (vec->rec_len + 1) & ~1; /* With align byte. */
1058 if (vec->rec_len == 3)
1060 /* Possibly end of file. Check the pattern. */
1061 if (vms_lib_bread_raw (abfd, vec->pattern, 4) != 4)
1062 return -1;
1063 if (!memcmp (vec->pattern, eotdesc + 2, 3))
1065 /* This is really an EOF. */
1066 vec->where += res;
1067 vec->file_len = vec->where;
1068 return res;
1072 if (vec->dcxsbms != NULL)
1074 /* This is a compressed member. */
1075 unsigned int len;
1076 file_ptr elen;
1078 /* Be sure there is enough room for the expansion. */
1079 len = (vec->rec_len + 1) & ~1;
1080 if (len > vec->dcx_max)
1082 while (len > vec->dcx_max)
1083 vec->dcx_max *= 2;
1084 vec->dcx_buf = bfd_alloc (abfd, vec->dcx_max);
1085 if (vec->dcx_buf == NULL)
1086 return -1;
1089 /* Read the compressed record. */
1090 vec->dcx_rlen = len;
1091 if (vec->rec_len == 3)
1093 /* Already read. */
1094 memcpy (vec->dcx_buf, vec->pattern, 3);
1096 else
1098 elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len);
1099 if (elen != len)
1100 return -1;
1103 /* Dummy expansion to get the expanded length. */
1104 vec->dcx_offset = 0;
1105 vec->dcx_sbm = vec->dcxsbms;
1106 vec->dcx_pos = 0;
1107 elen = vms_lib_dcx (vec, NULL, 0x10000);
1108 if (elen < 0)
1109 return -1;
1110 vec->rec_len = elen;
1111 vec->rec_rem = elen;
1113 /* Reset the state. */
1114 vec->dcx_offset = 0;
1115 vec->dcx_sbm = vec->dcxsbms;
1116 vec->dcx_pos = 0;
1119 if (vec->rec_pos < 0)
1121 unsigned char c;
1122 switch (vec->rec_pos)
1124 case REC_POS_LEN0:
1125 c = vec->rec_len & 0xff;
1126 vec->rec_pos = REC_POS_LEN1;
1127 break;
1128 case REC_POS_LEN1:
1129 c = (vec->rec_len >> 8) & 0xff;
1130 vec->rec_pos = 0;
1131 break;
1132 case REC_POS_PAD:
1133 c = 0;
1134 vec->rec_rem = 0;
1135 break;
1136 case REC_POS_NL:
1137 c = '\n';
1138 vec->rec_rem = 0;
1139 break;
1140 default:
1141 abort ();
1143 if (buf != NULL)
1145 *buf = c;
1146 buf++;
1148 nbytes--;
1149 res++;
1150 continue;
1153 if (nbytes > vec->rec_rem)
1154 chunk = vec->rec_rem;
1155 else
1156 chunk = nbytes;
1158 if (vec->dcxsbms != NULL)
1160 /* Optimize the stat() case: no need to decompress again as we
1161 know the length. */
1162 if (!(buf == NULL && chunk == vec->rec_rem))
1163 chunk = vms_lib_dcx (vec, buf, chunk);
1165 else
1167 if (vec->rec_len == 3)
1169 if (buf != NULL)
1170 memcpy (buf, vec->pattern + vec->rec_pos, chunk);
1172 else
1173 chunk = vms_lib_bread_raw (abfd, buf, chunk);
1175 if (chunk < 0)
1176 return -1;
1177 res += chunk;
1178 if (buf != NULL)
1179 buf += chunk;
1180 nbytes -= chunk;
1181 vec->rec_pos += chunk;
1182 vec->rec_rem -= chunk;
1184 if (vec->rec_rem == 0)
1186 /* End of record reached. */
1187 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
1189 if ((vec->rec_len & 1) == 1
1190 && vec->rec_len != 3
1191 && vec->dcxsbms == NULL)
1193 /* Eat the pad byte. */
1194 unsigned char pad;
1195 if (vms_lib_bread_raw (abfd, &pad, 1) != 1)
1196 return -1;
1198 vec->rec_pos = REC_POS_NL;
1199 vec->rec_rem = 1;
1201 else
1203 if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL)
1205 vec->rec_pos = REC_POS_PAD;
1206 vec->rec_rem = 1;
1211 vec->where += res;
1212 return res;
1215 /* Standard function, but we currently only handle the rewind case. */
1217 static int
1218 vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence)
1220 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1222 if (whence == SEEK_SET && offset == 0)
1224 vec->where = 0;
1225 vec->rec_rem = 0;
1226 vec->dcx_pos = -1;
1227 vec->blk_off = vec->init_blk_off;
1228 vec->next_block = vec->init_next_block;
1230 if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0)
1231 return -1;
1233 else
1234 abort ();
1235 return 0;
1238 static file_ptr
1239 vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED,
1240 const void *where ATTRIBUTE_UNUSED,
1241 file_ptr nbytes ATTRIBUTE_UNUSED)
1243 return -1;
1246 static int
1247 vms_lib_bclose (struct bfd *abfd)
1249 abfd->iostream = NULL;
1250 return 0;
1253 static int
1254 vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
1256 return 0;
1259 static int
1260 vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
1261 struct stat *sb ATTRIBUTE_UNUSED)
1263 /* Not supported. */
1264 return 0;
1267 static void *
1268 vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
1269 void *addr ATTRIBUTE_UNUSED,
1270 bfd_size_type len ATTRIBUTE_UNUSED,
1271 int prot ATTRIBUTE_UNUSED,
1272 int flags ATTRIBUTE_UNUSED,
1273 file_ptr offset ATTRIBUTE_UNUSED,
1274 void **map_addr ATTRIBUTE_UNUSED,
1275 bfd_size_type *map_len ATTRIBUTE_UNUSED)
1277 return (void *) -1;
1280 static const struct bfd_iovec vms_lib_iovec = {
1281 &vms_lib_bread, &vms_lib_bwrite, &vms_lib_btell, &vms_lib_bseek,
1282 &vms_lib_bclose, &vms_lib_bflush, &vms_lib_bstat, &vms_lib_bmmap
1285 /* Open a library module. FILEPOS is the position of the module header. */
1287 static bool
1288 vms_lib_bopen (bfd *el, file_ptr filepos)
1290 struct vms_lib_iovec *vec;
1291 unsigned char buf[256];
1292 struct vms_mhd *mhd;
1293 struct lib_tdata *tdata = bfd_libdata (el->my_archive);
1294 unsigned int len;
1296 /* Allocate and initialized the iovec. */
1297 vec = bfd_zalloc (el, sizeof (*vec));
1298 if (vec == NULL)
1299 return false;
1301 el->iostream = vec;
1302 el->iovec = &vms_lib_iovec;
1304 /* File length is not known. */
1305 vec->file_len = -1;
1307 /* Read the first data block. */
1308 vec->next_block = filepos & ~(VMS_BLOCK_SIZE - 1);
1309 vec->blk_off = DATA__LENGTH;
1310 if (!vms_lib_read_block (el))
1311 return false;
1313 /* Prepare to read the first record. */
1314 vec->blk_off = filepos & (VMS_BLOCK_SIZE - 1);
1315 vec->rec_rem = 0;
1316 if (bfd_seek (el->my_archive, filepos, SEEK_SET) != 0)
1317 return false;
1319 /* Read Record length + MHD + align byte. */
1320 len = tdata->mhd_size;
1321 if (vms_lib_bread_raw (el, buf, 2) != 2)
1322 return false;
1323 if (bfd_getl16 (buf) != len)
1324 return false;
1325 len = (len + 1) & ~1;
1326 BFD_ASSERT (len <= sizeof (buf));
1327 if (vms_lib_bread_raw (el, buf, len) != len)
1328 return false;
1330 /* Get info from mhd. */
1331 mhd = (struct vms_mhd *)buf;
1332 /* Check id. */
1333 if (mhd->id != MHD__C_MHDID)
1334 return false;
1335 if (len >= MHD__C_MHDLEN + 1)
1336 el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1337 el->mtime = vms_rawtime_to_time_t (mhd->datim);
1338 el->mtime_set = true;
1340 /* Reinit the iovec so that seek() will point to the first record after
1341 the mhd. */
1342 vec->where = 0;
1343 vec->init_blk_off = vec->blk_off;
1344 vec->init_next_block = vec->next_block;
1345 vec->first_block = bfd_tell (el->my_archive);
1346 vec->dcxsbms = bfd_libdata (el->my_archive)->dcxsbm;
1348 if (vec->dcxsbms != NULL)
1350 /* Handle DCX. */
1351 vec->dcx_max = 10 * 1024;
1352 vec->dcx_buf = bfd_alloc (el, vec->dcx_max);
1353 vec->dcx_pos = -1;
1354 if (vec->dcx_buf == NULL)
1355 return -1;
1357 return true;
1360 /* Get member MODIDX. Return NULL in case of error. */
1362 static bfd *
1363 _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
1365 struct lib_tdata *tdata = bfd_libdata (abfd);
1366 bfd *res;
1367 file_ptr file_off;
1368 const char *name;
1369 char *newname;
1370 size_t namelen;
1372 /* Sanity check. */
1373 if (modidx >= tdata->nbr_modules)
1374 return NULL;
1376 /* Already loaded. */
1377 if (tdata->cache[modidx])
1378 return tdata->cache[modidx];
1380 /* Build it. */
1381 file_off = tdata->modules[modidx].file_offset;
1382 if (tdata->type != LBR__C_TYP_IOBJ)
1384 res = _bfd_create_empty_archive_element_shell (abfd);
1385 if (res == NULL)
1386 return NULL;
1388 /* Special reader to deal with data blocks. */
1389 if (!vms_lib_bopen (res, file_off))
1390 return NULL;
1392 else
1394 char buf[256];
1395 struct vms_mhd *mhd;
1396 struct areltdata *arelt;
1398 /* Sanity check. The MHD must be big enough to contain module size. */
1399 if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4)
1400 return NULL;
1402 /* Read the MHD now. */
1403 if (bfd_seek (abfd, file_off, SEEK_SET) != 0)
1404 return NULL;
1405 if (bfd_bread (buf, tdata->mhd_size, abfd) != tdata->mhd_size)
1406 return NULL;
1408 mhd = (struct vms_mhd *) buf;
1409 if (mhd->id != MHD__C_MHDID)
1410 return NULL;
1412 res = _bfd_create_empty_archive_element_shell (abfd);
1413 if (res == NULL)
1414 return NULL;
1415 arelt = bfd_zmalloc (sizeof (*arelt));
1416 if (arelt == NULL)
1418 bfd_close (res);
1419 return NULL;
1421 res->arelt_data = arelt;
1423 /* Get info from mhd. */
1424 if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1)
1425 res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1426 res->mtime = vms_rawtime_to_time_t (mhd->datim);
1427 res->mtime_set = true;
1429 arelt->parsed_size = bfd_getl32 (mhd->modsize);
1431 /* No need for a special reader as members are stored linearly.
1432 Just skip the MHD. */
1433 res->origin = file_off + tdata->mhd_size;
1436 /* Set filename. */
1437 name = tdata->modules[modidx].name;
1438 namelen = strlen (name);
1439 newname = bfd_malloc (namelen + 4 + 1);
1440 if (newname == NULL)
1442 bfd_close (res);
1443 return NULL;
1445 strcpy (newname, name);
1446 switch (tdata->type)
1448 case LBR__C_TYP_IOBJ:
1449 case LBR__C_TYP_EOBJ:
1450 /* For object archives, append .obj to mimic standard behaviour. */
1451 strcpy (newname + namelen, ".obj");
1452 break;
1453 default:
1454 break;
1456 bfd_set_filename (res, newname);
1457 free (newname);
1458 if (bfd_get_filename (res) == NULL)
1460 bfd_close (res);
1461 return NULL;
1464 tdata->cache[modidx] = res;
1466 return res;
1469 /* Standard function: get member at IDX. */
1471 bfd *
1472 _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
1474 struct lib_tdata *tdata = bfd_libdata (abfd);
1475 file_ptr file_off;
1476 unsigned int modidx;
1478 /* Check symidx. */
1479 if (symidx > tdata->artdata.symdef_count)
1480 return NULL;
1481 file_off = tdata->artdata.symdefs[symidx].file_offset;
1483 /* Linear-scan. */
1484 for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
1486 if (tdata->modules[modidx].file_offset == file_off)
1487 break;
1489 if (modidx >= tdata->nbr_modules)
1490 return NULL;
1492 return _bfd_vms_lib_get_module (abfd, modidx);
1495 /* Elements of an imagelib are stubs. You can get the real image with this
1496 function. */
1498 bfd *
1499 _bfd_vms_lib_get_imagelib_file (bfd *el)
1501 bfd *archive = el->my_archive;
1502 const char *modname = bfd_get_filename (el);
1503 int modlen = strlen (modname);
1504 char *filename;
1505 int j;
1506 bfd *res;
1508 /* Convert module name to lower case and append '.exe'. */
1509 filename = bfd_alloc (el, modlen + 5);
1510 if (filename == NULL)
1511 return NULL;
1512 for (j = 0; j < modlen; j++)
1513 if (ISALPHA (modname[j]))
1514 filename[j] = TOLOWER (modname[j]);
1515 else
1516 filename[j] = modname[j];
1517 memcpy (filename + modlen, ".exe", 5);
1519 filename = _bfd_append_relative_path (archive, filename);
1520 if (filename == NULL)
1521 return NULL;
1522 res = bfd_openr (filename, NULL);
1524 if (res == NULL)
1526 /* xgettext:c-format */
1527 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1528 filename, bfd_get_filename (archive));
1529 bfd_release (archive, filename);
1530 return NULL;
1533 /* FIXME: put it in a cache ? */
1534 return res;
1537 /* Standard function. */
1539 bfd *
1540 _bfd_vms_lib_openr_next_archived_file (bfd *archive,
1541 bfd *last_file)
1543 unsigned int idx;
1544 bfd *res;
1546 if (!last_file)
1547 idx = 0;
1548 else
1549 idx = last_file->proxy_origin + 1;
1551 if (idx >= bfd_libdata (archive)->nbr_modules)
1553 bfd_set_error (bfd_error_no_more_archived_files);
1554 return NULL;
1557 res = _bfd_vms_lib_get_module (archive, idx);
1558 if (res == NULL)
1559 return res;
1560 res->proxy_origin = idx;
1561 return res;
1564 /* Standard function. Just compute the length. */
1567 _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
1569 struct lib_tdata *tdata;
1571 /* Sanity check. */
1572 if (abfd->my_archive == NULL)
1574 bfd_set_error (bfd_error_invalid_operation);
1575 return -1;
1578 tdata = bfd_libdata (abfd->my_archive);
1579 if (tdata->type != LBR__C_TYP_IOBJ)
1581 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1583 if (vec->file_len == (ufile_ptr)-1)
1585 if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
1586 return -1;
1588 /* Compute length. */
1589 while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
1592 st->st_size = vec->file_len;
1594 else
1596 st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
1599 if (abfd->mtime_set)
1600 st->st_mtime = abfd->mtime;
1601 else
1602 st->st_mtime = 0;
1603 st->st_uid = 0;
1604 st->st_gid = 0;
1605 st->st_mode = 0644;
1607 return 0;
1610 /* Internal representation of an index entry. */
1612 struct lib_index
1614 /* Corresponding archive member. */
1615 bfd *abfd;
1617 /* Number of reference to this entry. */
1618 unsigned int ref;
1620 /* Length of the key. */
1621 unsigned short namlen;
1623 /* Key. */
1624 const char *name;
1627 /* Used to sort index entries. */
1629 static int
1630 lib_index_cmp (const void *lv, const void *rv)
1632 const struct lib_index *l = lv;
1633 const struct lib_index *r = rv;
1635 return strcmp (l->name, r->name);
1638 /* Maximum number of index blocks level. */
1640 #define MAX_LEVEL 10
1642 /* Get the size of an index entry. */
1644 static unsigned int
1645 get_idxlen (struct lib_index *idx, bool is_elfidx)
1647 if (is_elfidx)
1649 /* 9 is the size of struct vms_elfidx without keyname. */
1650 if (idx->namlen > MAX_KEYLEN)
1651 return 9 + sizeof (struct vms_kbn);
1652 else
1653 return 9 + idx->namlen;
1655 else
1657 /* 7 is the size of struct vms_idx without keyname. */
1658 return 7 + idx->namlen;
1662 /* Write the index composed by NBR symbols contained in IDX.
1663 VBN is the first vbn to be used, and will contain on return the last vbn.
1664 Can be called with ABFD set to NULL just to size the index.
1665 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1666 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1667 Return TRUE on success. */
1669 static bool
1670 vms_write_index (bfd *abfd,
1671 struct lib_index *idx, unsigned int nbr, unsigned int *vbn,
1672 unsigned int *topvbn, bool is_elfidx)
1674 /* The index is organized as a tree. This function implements a naive
1675 algorithm to balance the tree: it fills the leaves, and create a new
1676 branch when all upper leaves and branches are full. We only keep in
1677 memory a path to the current leaf. */
1678 unsigned int i;
1679 int j;
1680 int level;
1681 /* Disk blocks for the current path. */
1682 struct vms_indexdef *rblk[MAX_LEVEL];
1683 /* Info on the current blocks. */
1684 struct idxblk
1686 unsigned int vbn; /* VBN of the block. */
1687 /* The last entry is identified so that it could be copied to the
1688 parent block. */
1689 unsigned short len; /* Length up to the last entry. */
1690 unsigned short lastlen; /* Length of the last entry. */
1691 } blk[MAX_LEVEL];
1693 /* The kbn blocks are used to store long symbol names. */
1694 unsigned int kbn_sz = 0; /* Number of bytes available in the kbn block. */
1695 unsigned int kbn_vbn = 0; /* VBN of the kbn block. */
1696 unsigned char *kbn_blk = NULL; /* Contents of the kbn block. */
1698 if (nbr == 0)
1700 /* No entries. Very easy to handle. */
1701 if (topvbn != NULL)
1702 *topvbn = 0;
1703 return true;
1706 if (abfd == NULL)
1708 /* Sort the index the first time this function is called. */
1709 qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp);
1712 /* Allocate first index block. */
1713 level = 1;
1714 if (abfd != NULL)
1715 rblk[0] = bfd_zmalloc (sizeof (struct vms_indexdef));
1716 blk[0].vbn = (*vbn)++;
1717 blk[0].len = 0;
1718 blk[0].lastlen = 0;
1720 for (i = 0; i < nbr; i++, idx++)
1722 unsigned int idxlen;
1723 int flush = 0;
1724 unsigned int key_vbn = 0;
1725 unsigned int key_off = 0;
1727 idxlen = get_idxlen (idx, is_elfidx);
1729 if (is_elfidx && idx->namlen > MAX_KEYLEN)
1731 /* If the key (ie name) is too long, write it in the kbn block. */
1732 unsigned int kl = idx->namlen;
1733 unsigned int kl_chunk;
1734 const char *key = idx->name;
1736 /* Write the key in the kbn, chunk after chunk. */
1739 if (kbn_sz < sizeof (struct vms_kbn))
1741 /* Not enough room in the kbn block. */
1742 if (abfd != NULL)
1744 /* Write it to the disk (if there is one). */
1745 if (kbn_vbn != 0)
1747 if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
1748 return false;
1750 else
1752 kbn_blk = bfd_malloc (VMS_BLOCK_SIZE);
1753 if (kbn_blk == NULL)
1754 return false;
1756 *(unsigned short *)kbn_blk = 0;
1758 /* Allocate a new block for the keys. */
1759 kbn_vbn = (*vbn)++;
1760 kbn_sz = VMS_BLOCK_SIZE - 2;
1762 /* Size of the chunk written to the current key block. */
1763 if (kl + sizeof (struct vms_kbn) > kbn_sz)
1764 kl_chunk = kbn_sz - sizeof (struct vms_kbn);
1765 else
1766 kl_chunk = kl;
1768 if (kbn_blk != NULL)
1770 struct vms_kbn *kbn;
1772 kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz);
1774 if (key_vbn == 0)
1776 /* Save the rfa of the first chunk. */
1777 key_vbn = kbn_vbn;
1778 key_off = VMS_BLOCK_SIZE - kbn_sz;
1781 bfd_putl16 (kl_chunk, kbn->keylen);
1782 if (kl_chunk == kl)
1784 /* No next chunk. */
1785 bfd_putl32 (0, kbn->rfa.vbn);
1786 bfd_putl16 (0, kbn->rfa.offset);
1788 else
1790 /* Next chunk will be at the start of the next block. */
1791 bfd_putl32 (*vbn, kbn->rfa.vbn);
1792 bfd_putl16 (2, kbn->rfa.offset);
1794 memcpy ((char *)(kbn + 1), key, kl_chunk);
1795 key += kl_chunk;
1797 kl -= kl_chunk;
1798 kl_chunk = (kl_chunk + 1) & ~1; /* Always align. */
1799 kbn_sz -= kl_chunk + sizeof (struct vms_kbn);
1801 while (kl > 0);
1804 /* Check if a block might overflow. In this case we will flush this
1805 block and all the blocks below it. */
1806 for (j = 0; j < level; j++)
1807 if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ)
1808 flush = j + 1;
1810 for (j = 0; j < level; j++)
1812 if (j < flush)
1814 /* There is not enough room to write the new entry in this
1815 block or in a parent block. */
1817 if (j + 1 == level)
1819 BFD_ASSERT (level < MAX_LEVEL);
1821 /* Need to create a parent. */
1822 if (abfd != NULL)
1824 rblk[level] = bfd_zmalloc (sizeof (struct vms_indexdef));
1825 bfd_putl32 (*vbn, rblk[j]->parent);
1827 blk[level].vbn = (*vbn)++;
1828 blk[level].len = 0;
1829 blk[level].lastlen = blk[j].lastlen;
1831 level++;
1834 /* Update parent block: write the last entry from the current
1835 block. */
1836 if (abfd != NULL)
1838 struct vms_rfa *rfa;
1840 /* Pointer to the last entry in parent block. */
1841 rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len);
1843 /* Copy the whole entry. */
1844 BFD_ASSERT (blk[j + 1].lastlen == blk[j].lastlen);
1845 memcpy (rfa, rblk[j]->keys + blk[j].len, blk[j].lastlen);
1846 /* Fix the entry (which in always the first field of an
1847 entry. */
1848 bfd_putl32 (blk[j].vbn, rfa->vbn);
1849 bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
1852 if (j + 1 == flush)
1854 /* And allocate it. Do it only on the block that won't be
1855 flushed (so that the parent of the parent can be
1856 updated too). */
1857 blk[j + 1].len += blk[j + 1].lastlen;
1858 blk[j + 1].lastlen = 0;
1861 /* Write this block on the disk. */
1862 if (abfd != NULL)
1864 bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1865 if (!vms_write_block (abfd, blk[j].vbn, rblk[j]))
1866 return false;
1869 /* Reset this block. */
1870 blk[j].len = 0;
1871 blk[j].lastlen = 0;
1872 blk[j].vbn = (*vbn)++;
1875 /* Append it to the block. */
1876 if (j == 0)
1878 /* Keep the previous last entry. */
1879 blk[j].len += blk[j].lastlen;
1881 if (abfd != NULL)
1883 struct vms_rfa *rfa;
1885 rfa = (struct vms_rfa *)(rblk[j]->keys + blk[j].len);
1886 bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
1887 rfa->vbn);
1888 bfd_putl16
1889 ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE)
1890 + (is_elfidx ? 0 : DATA__DATA),
1891 rfa->offset);
1893 if (is_elfidx)
1895 /* Use elfidx format. */
1896 struct vms_elfidx *en = (struct vms_elfidx *)rfa;
1898 en->flags = 0;
1899 if (key_vbn != 0)
1901 /* Long symbol name. */
1902 struct vms_kbn *k = (struct vms_kbn *)(en->keyname);
1903 bfd_putl16 (sizeof (struct vms_kbn), en->keylen);
1904 bfd_putl16 (idx->namlen, k->keylen);
1905 bfd_putl32 (key_vbn, k->rfa.vbn);
1906 bfd_putl16 (key_off, k->rfa.offset);
1907 en->flags |= ELFIDX__SYMESC;
1909 else
1911 bfd_putl16 (idx->namlen, en->keylen);
1912 memcpy (en->keyname, idx->name, idx->namlen);
1915 else
1917 /* Use idx format. */
1918 struct vms_idx *en = (struct vms_idx *)rfa;
1919 en->keylen = idx->namlen;
1920 memcpy (en->keyname, idx->name, idx->namlen);
1924 /* The last added key can now be the last one all blocks in the
1925 path. */
1926 blk[j].lastlen = idxlen;
1930 /* Save VBN of the root. */
1931 if (topvbn != NULL)
1932 *topvbn = blk[level - 1].vbn;
1934 if (abfd == NULL)
1935 return true;
1937 /* Flush. */
1938 for (j = 1; j < level; j++)
1940 /* Update parent block: write the new entry. */
1941 unsigned char *en;
1942 unsigned char *par;
1943 struct vms_rfa *rfa;
1945 en = rblk[j - 1]->keys + blk[j - 1].len;
1946 par = rblk[j]->keys + blk[j].len;
1947 BFD_ASSERT (blk[j].lastlen == blk[j - 1].lastlen);
1948 memcpy (par, en, blk[j - 1].lastlen);
1949 rfa = (struct vms_rfa *)par;
1950 bfd_putl32 (blk[j - 1].vbn, rfa->vbn);
1951 bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
1954 for (j = 0; j < level; j++)
1956 /* Write this block on the disk. */
1957 bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1958 if (!vms_write_block (abfd, blk[j].vbn, rblk[j]))
1959 return false;
1961 free (rblk[j]);
1964 /* Write the last kbn (if any). */
1965 if (kbn_vbn != 0)
1967 if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
1968 return false;
1969 free (kbn_blk);
1972 return true;
1975 /* Append data to the data block DATA. Force write if PAD is true. */
1977 static bool
1978 vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off,
1979 const unsigned char *buf, unsigned int len, int pad)
1981 while (len > 0 || pad)
1983 unsigned int doff = *off & (VMS_BLOCK_SIZE - 1);
1984 unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff;
1985 unsigned int l;
1987 l = (len > remlen) ? remlen : len;
1988 memcpy (data->data + doff, buf, l);
1989 buf += l;
1990 len -= l;
1991 doff += l;
1992 *off += l;
1994 if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad))
1996 data->recs = 0;
1997 data->fill_1 = 0;
1998 bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link);
2000 if (bfd_bwrite (data, sizeof (*data), arch) != sizeof (*data))
2001 return false;
2003 *off += DATA__LENGTH - doff;
2005 if (len == 0)
2006 break;
2009 return true;
2012 /* Build the symbols index. */
2014 static bool
2015 _bfd_vms_lib_build_map (unsigned int nbr_modules,
2016 struct lib_index *modules,
2017 unsigned int *res_cnt,
2018 struct lib_index **res)
2020 unsigned int i;
2021 asymbol **syms = NULL;
2022 long syms_max = 0;
2023 struct lib_index *map = NULL;
2024 unsigned int map_max = 1024; /* Fine initial default. */
2025 unsigned int map_count = 0;
2027 map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index));
2028 if (map == NULL)
2029 goto error_return;
2031 /* Gather symbols. */
2032 for (i = 0; i < nbr_modules; i++)
2034 long storage;
2035 long symcount;
2036 long src_count;
2037 bfd *current = modules[i].abfd;
2039 if ((bfd_get_file_flags (current) & HAS_SYMS) == 0)
2040 continue;
2042 storage = bfd_get_symtab_upper_bound (current);
2043 if (storage < 0)
2044 goto error_return;
2046 if (storage != 0)
2048 if (storage > syms_max)
2050 free (syms);
2051 syms_max = storage;
2052 syms = (asymbol **) bfd_malloc (syms_max);
2053 if (syms == NULL)
2054 goto error_return;
2056 symcount = bfd_canonicalize_symtab (current, syms);
2057 if (symcount < 0)
2058 goto error_return;
2060 /* Now map over all the symbols, picking out the ones we
2061 want. */
2062 for (src_count = 0; src_count < symcount; src_count++)
2064 flagword flags = (syms[src_count])->flags;
2065 asection *sec = syms[src_count]->section;
2067 if ((flags & BSF_GLOBAL
2068 || flags & BSF_WEAK
2069 || flags & BSF_INDIRECT
2070 || bfd_is_com_section (sec))
2071 && ! bfd_is_und_section (sec))
2073 struct lib_index *new_map;
2075 /* This symbol will go into the archive header. */
2076 if (map_count == map_max)
2078 map_max *= 2;
2079 new_map = (struct lib_index *)
2080 bfd_realloc (map, map_max * sizeof (struct lib_index));
2081 if (new_map == NULL)
2082 goto error_return;
2083 map = new_map;
2086 map[map_count].abfd = current;
2087 map[map_count].namlen = strlen (syms[src_count]->name);
2088 map[map_count].name = syms[src_count]->name;
2089 map_count++;
2090 modules[i].ref++;
2096 *res_cnt = map_count;
2097 *res = map;
2098 return true;
2100 error_return:
2101 free (syms);
2102 free (map);
2103 return false;
2106 /* Do the hard work: write an archive on the disk. */
2108 bool
2109 _bfd_vms_lib_write_archive_contents (bfd *arch)
2111 bfd *current;
2112 unsigned int nbr_modules;
2113 struct lib_index *modules;
2114 unsigned int nbr_symbols;
2115 struct lib_index *symbols;
2116 struct lib_tdata *tdata = bfd_libdata (arch);
2117 unsigned int i;
2118 file_ptr off;
2119 unsigned int nbr_mod_iblk;
2120 unsigned int nbr_sym_iblk;
2121 unsigned int vbn;
2122 unsigned int mod_idx_vbn;
2123 unsigned int sym_idx_vbn;
2124 bool is_elfidx = tdata->kind == vms_lib_ia64;
2125 unsigned int max_keylen = is_elfidx ? MAX_EKEYLEN : MAX_KEYLEN;
2127 /* Count the number of modules (and do a first sanity check). */
2128 nbr_modules = 0;
2129 for (current = arch->archive_head;
2130 current != NULL;
2131 current = current->archive_next)
2133 /* This check is checking the bfds for the objects we're reading
2134 from (which are usually either an object file or archive on
2135 disk), not the archive entries we're writing to. We don't
2136 actually create bfds for the archive members, we just copy
2137 them byte-wise when we write out the archive. */
2138 if (bfd_write_p (current) || !bfd_check_format (current, bfd_object))
2140 bfd_set_error (bfd_error_invalid_operation);
2141 goto input_err;
2144 nbr_modules++;
2147 /* Build the modules list. */
2148 BFD_ASSERT (tdata->modules == NULL);
2149 modules = bfd_alloc (arch, nbr_modules * sizeof (struct lib_index));
2150 if (modules == NULL)
2151 return false;
2153 for (current = arch->archive_head, i = 0;
2154 current != NULL;
2155 current = current->archive_next, i++)
2157 unsigned int nl;
2159 modules[i].abfd = current;
2160 modules[i].name = vms_get_module_name (bfd_get_filename (current), false);
2161 modules[i].ref = 1;
2163 /* FIXME: silently truncate long names ? */
2164 nl = strlen (modules[i].name);
2165 modules[i].namlen = (nl > max_keylen ? max_keylen : nl);
2168 /* Create the module index. */
2169 vbn = 0;
2170 if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL, is_elfidx))
2171 return false;
2172 nbr_mod_iblk = vbn;
2174 /* Create symbol index. */
2175 if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols))
2176 return false;
2178 vbn = 0;
2179 if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx))
2180 return false;
2181 nbr_sym_iblk = vbn;
2183 /* Write modules and remember their position. */
2184 off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE;
2186 if (bfd_seek (arch, off, SEEK_SET) != 0)
2187 return false;
2189 for (i = 0; i < nbr_modules; i++)
2191 struct vms_datadef data;
2192 unsigned char blk[VMS_BLOCK_SIZE];
2193 struct vms_mhd *mhd;
2194 unsigned int sz;
2196 current = modules[i].abfd;
2197 current->proxy_origin = off;
2199 if (is_elfidx)
2200 sz = 0;
2201 else
2203 /* Write the MHD as a record (ie, size first). */
2204 sz = 2;
2205 bfd_putl16 (tdata->mhd_size, blk);
2207 mhd = (struct vms_mhd *)(blk + sz);
2208 memset (mhd, 0, sizeof (struct vms_mhd));
2209 mhd->lbrflag = 0;
2210 mhd->id = MHD__C_MHDID;
2211 mhd->objidlng = 4;
2212 memcpy (mhd->objid, "V1.0", 4);
2213 bfd_putl32 (modules[i].ref, mhd->refcnt);
2214 /* FIXME: datim. */
2216 sz += tdata->mhd_size;
2217 sz = (sz + 1) & ~1;
2219 /* Rewind the member to be put into the archive. */
2220 if (bfd_seek (current, 0, SEEK_SET) != 0)
2221 goto input_err;
2223 /* Copy the member into the archive. */
2224 if (is_elfidx)
2226 unsigned int modsize = 0;
2227 bfd_size_type amt;
2228 file_ptr off_hdr = off;
2230 /* Read to complete the first block. */
2231 amt = bfd_bread (blk + sz, VMS_BLOCK_SIZE - sz, current);
2232 if (amt == (bfd_size_type)-1)
2233 goto input_err;
2234 modsize = amt;
2235 if (amt < VMS_BLOCK_SIZE - sz)
2237 /* The member size is less than a block. Pad the block. */
2238 memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt);
2240 bfd_putl32 (modsize, mhd->modsize);
2242 /* Write the first block (which contains an mhd). */
2243 if (bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
2244 goto input_err;
2245 off += VMS_BLOCK_SIZE;
2247 if (amt == VMS_BLOCK_SIZE - sz)
2249 /* Copy the remaining. */
2250 char buffer[DEFAULT_BUFFERSIZE];
2252 while (1)
2254 amt = bfd_bread (buffer, sizeof (buffer), current);
2255 if (amt == (bfd_size_type)-1)
2256 goto input_err;
2257 if (amt == 0)
2258 break;
2259 modsize += amt;
2260 if (amt != sizeof (buffer))
2262 /* Clear the padding. */
2263 memset (buffer + amt, 0, sizeof (buffer) - amt);
2264 amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
2266 if (bfd_bwrite (buffer, amt, arch) != amt)
2267 goto input_err;
2268 off += amt;
2271 /* Now that the size is known, write the first block (again). */
2272 bfd_putl32 (modsize, mhd->modsize);
2273 if (bfd_seek (arch, off_hdr, SEEK_SET) != 0
2274 || bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
2275 goto input_err;
2276 if (bfd_seek (arch, off, SEEK_SET) != 0)
2277 goto input_err;
2280 else
2282 /* Write the MHD. */
2283 if (!vms_write_data_block (arch, &data, &off, blk, sz, 0))
2284 goto input_err;
2286 /* Write the member. */
2287 while (1)
2289 sz = bfd_bread (blk, sizeof (blk), current);
2290 if (sz == 0)
2291 break;
2292 if (!vms_write_data_block (arch, &data, &off, blk, sz, 0))
2293 goto input_err;
2296 /* Write the end of module marker. */
2297 if (!vms_write_data_block (arch, &data, &off,
2298 eotdesc, sizeof (eotdesc), 1))
2299 goto input_err;
2303 /* Write the indexes. */
2304 vbn = 2;
2305 if (!vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn,
2306 is_elfidx))
2307 return false;
2308 if (!vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn,
2309 is_elfidx))
2310 return false;
2312 /* Write libary header. */
2314 unsigned char blk[VMS_BLOCK_SIZE];
2315 struct vms_lhd *lhd = (struct vms_lhd *)blk;
2316 struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
2317 unsigned int idd_flags;
2318 unsigned int saneid;
2320 memset (blk, 0, sizeof (blk));
2322 lhd->type = tdata->type;
2323 lhd->nindex = 2;
2324 switch (tdata->kind)
2326 case vms_lib_alpha:
2327 saneid = LHD_SANEID3;
2328 break;
2329 case vms_lib_ia64:
2330 saneid = LHD_SANEID6;
2331 break;
2332 default:
2333 abort ();
2335 bfd_putl32 (saneid, lhd->sanity);
2336 bfd_putl16 (tdata->ver, lhd->majorid);
2337 bfd_putl16 (0, lhd->minorid);
2338 snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
2339 "GNU ar %u.%u.%u",
2340 (unsigned)(BFD_VERSION / 100000000UL),
2341 (unsigned)(BFD_VERSION / 1000000UL) % 100,
2342 (unsigned)(BFD_VERSION / 10000UL) % 100);
2343 lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
2344 lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
2346 bfd_putl32 (tdata->credat_lo, lhd->credat + 0);
2347 bfd_putl32 (tdata->credat_hi, lhd->credat + 4);
2348 vms_raw_get_time (lhd->updtim);
2350 lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT;
2352 bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
2353 bfd_putl32 (nbr_modules, lhd->modcnt);
2354 bfd_putl32 (nbr_modules, lhd->modhdrs);
2356 /* Number of blocks for index. */
2357 bfd_putl32 (nbr_mod_iblk + nbr_sym_iblk, lhd->idxblks);
2358 bfd_putl32 (vbn - 1, lhd->hipreal);
2359 bfd_putl32 (vbn - 1, lhd->hiprusd);
2361 /* VBN of the next free block. */
2362 bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextvbn);
2363 bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextrfa + 0);
2364 bfd_putl16 (0, lhd->nextrfa + 4);
2366 /* First index (modules name). */
2367 idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX
2368 | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR;
2369 bfd_putl16 (idd_flags, idd->flags);
2370 bfd_putl16 (max_keylen + 1, idd->keylen);
2371 bfd_putl16 (mod_idx_vbn, idd->vbn);
2372 idd++;
2374 /* Second index (symbols name). */
2375 bfd_putl16 (idd_flags, idd->flags);
2376 bfd_putl16 (max_keylen + 1, idd->keylen);
2377 bfd_putl16 (sym_idx_vbn, idd->vbn);
2378 idd++;
2380 if (!vms_write_block (arch, 1, blk))
2381 return false;
2384 return true;
2386 input_err:
2387 bfd_set_input_error (current, bfd_get_error ());
2388 return false;
2391 /* Add a target for text library. This costs almost nothing and is useful to
2392 read VMS library on the host. */
2394 const bfd_target alpha_vms_lib_txt_vec =
2396 "vms-libtxt", /* Name. */
2397 bfd_target_unknown_flavour,
2398 BFD_ENDIAN_UNKNOWN, /* byteorder */
2399 BFD_ENDIAN_UNKNOWN, /* header_byteorder */
2400 0, /* Object flags. */
2401 0, /* Sect flags. */
2402 0, /* symbol_leading_char. */
2403 ' ', /* ar_pad_char. */
2404 15, /* ar_max_namelen. */
2405 0, /* match priority. */
2406 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
2407 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2408 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2409 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
2410 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2411 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2412 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
2413 { /* bfd_check_format. */
2414 _bfd_dummy_target,
2415 _bfd_dummy_target,
2416 _bfd_vms_lib_txt_archive_p,
2417 _bfd_dummy_target
2419 { /* bfd_set_format. */
2420 _bfd_bool_bfd_false_error,
2421 _bfd_bool_bfd_false_error,
2422 _bfd_bool_bfd_false_error,
2423 _bfd_bool_bfd_false_error
2425 { /* bfd_write_contents. */
2426 _bfd_bool_bfd_false_error,
2427 _bfd_bool_bfd_false_error,
2428 _bfd_bool_bfd_false_error,
2429 _bfd_bool_bfd_false_error
2431 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
2432 BFD_JUMP_TABLE_COPY (_bfd_generic),
2433 BFD_JUMP_TABLE_CORE (_bfd_nocore),
2434 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
2435 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
2436 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
2437 BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
2438 BFD_JUMP_TABLE_LINK (_bfd_nolink),
2439 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2441 NULL,
2443 NULL