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