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